void DisableActionsForControl(InputControl control, InputActionsProcessor inputActionsProcessor) { foreach (var action in inputActionsProcessor.inputActions) { if (action == null) { continue; } foreach (var otherControl in action.controls) //TODO Should use active control instead of all controls? { if (!control.path.Contains(otherControl.path) && !otherControl.path.Contains(control.path)) { continue; } // Disable will send a cancelled callback to started actions, but that will be consumed for our listeners. Manually invoke those callbacks now action.Disable(); var startedOrPerformed = action.phase == InputActionPhase.Started || action.phase == InputActionPhase.Performed; if (startedOrPerformed && m_ActionListeners.TryGetValue(action, out var listeners)) { foreach (var listener in listeners.cancelledCallbacks) { try { listener.Invoke(); } catch (Exception exception) { Debug.LogException(exception); } } } if (m_ConsumedActions.TryGetValue(control, out var list)) { if (!list.Contains(action)) { list.Add(action); } } else { m_ConsumedActions.Add(control, new List <InputAction>() { action }); } } } }
InputActionAsset IProvidesInputActions.CreateActions(IUsesInputActions user, InputDevice device) { var actionsAsset = user.inputActionsAsset; if (actionsAsset == null) { return(null); } var inputActions = Instantiate(actionsAsset); if (inputActions == null) { return(null); } if (device != null) { inputActions.devices = new[] { device } } ; inputActions.Enable(); var order = 0; var attributes = user.GetType().GetCustomAttributes(typeof(ProcessInputAttribute), true); var processInputAttribute = attributes.Length > 0 ? (ProcessInputAttribute)attributes[0] : null; if (processInputAttribute != null) { order = processInputAttribute.order; } var inputActionsProcessor = new InputActionsProcessor { user = user, inputActions = inputActions, order = order, actionsAsset = actionsAsset }; m_InputProcessors.Add(inputActionsProcessor); m_InputProcessors.Sort((a, b) => a.order.CompareTo(b.order)); //TODO Implicit ordering tool stack priority // New action map needs to disable any actions bound to currently locked controls foreach (var lockedControl in m_LockedControls) { DisableActionsForControl(lockedControl.Key, inputActionsProcessor); } user.OnActionsCreated(inputActions); return(inputActions); }
void SendEventsToInputProcessor(InputActionsProcessor inputActionsProcessor) { if (m_AccumulatedStartedEvents.TryGetValue(inputActionsProcessor.user, out var startEvents)) { foreach (var eventContext in startEvents) { if (m_ActionListeners.TryGetValue(eventContext.action, out var listeners)) { ExecuteActionListeners(eventContext, listeners.startedCallbacks); } } startEvents.Clear(); //TODO events that were consumed should be held onto in case a control wants to cancel a consumption and allow the past events to now be sent retroactively. } if (m_AccumulatedPerformedEvents.TryGetValue(inputActionsProcessor.user, out var performEvents)) { foreach (var eventContext in performEvents) { if (m_ActionListeners.TryGetValue(eventContext.action, out var listeners)) { ExecuteActionListeners(eventContext, listeners.performedCallbacks); } } performEvents.Clear(); } if (m_AccumulatedCanceledEvents.TryGetValue(inputActionsProcessor.user, out var cancelEvents)) { foreach (var eventContext in cancelEvents) { if (m_ActionListeners.TryGetValue(eventContext.action, out var listeners)) { ExecuteActionListeners(eventContext, listeners.cancelledCallbacks); } } cancelEvents.Clear(); } }