public static void QueueEvent(InputEventPtr eventPtr) { NativeInputSystem.QueueInputEvent(eventPtr.data); }
public static unsafe void WriteValueFromObjectIntoEvent(this InputControl control, InputEventPtr eventPtr, object value) { if (control == null) { throw new ArgumentNullException(nameof(control)); } var statePtr = control.GetStatePtrFromStateEvent(eventPtr); if (statePtr == null) { return; } control.WriteValueFromObjectIntoState(value, statePtr); }
public static unsafe void WriteValueIntoEvent <TValue>(this InputControl <TValue> control, TValue value, InputEventPtr eventPtr) where TValue : struct { if (control == null) { throw new ArgumentNullException(nameof(control)); } if (!eventPtr.valid) { throw new ArgumentNullException(nameof(eventPtr)); } var statePtr = control.GetStatePtrFromStateEvent(eventPtr); if (statePtr == null) { return; } control.WriteValueIntoState(value, statePtr); }
void QueueEvent(InputEventPtr iep) { InputSystem.QueueEvent(iep); }
public static TValue ReadUnprocessedValueFromEvent <TValue>(this InputControl <TValue> control, InputEventPtr eventPtr) where TValue : struct { if (control == null) { throw new ArgumentNullException(nameof(control)); } var result = default(TValue); control.ReadUnprocessedValueFromEvent(eventPtr, out result); return(result); }
/// <summary> /// Implements <see cref="IInputStateCallbackReceiver.OnStateEvent"/> for the mouse. /// </summary> /// <param name="eventPtr"></param> protected new unsafe void OnStateEvent(InputEventPtr eventPtr) { scroll.AccumulateValueInEvent(currentStatePtr, eventPtr); base.OnStateEvent(eventPtr); }
bool IInputStateCallbackReceiver.GetStateOffsetForEvent(InputControl control, InputEventPtr eventPtr, ref uint offset) { return(false); }
public void OnEventFormatMismatch(InputEventPtr eventPtr, InputDevice device) { Debug.LogError(string.Format("'{0}' input event for device '{1}' has incorrect format (event format: '{2}', device format: '{3}')", eventPtr.type, device, eventPtr.type, device.stateBlock.format)); }
public void OnEventForDisabledDevice(InputEventPtr eventPtr, InputDevice device) { Debug.LogError(string.Format("Device '{1}' received input event '{0}' but the device is disabled", eventPtr, device)); }
private unsafe void OnEvent(InputEventPtr eventPtr) { // Ignore if not a state event. if (!eventPtr.IsA <StateEvent>() && !eventPtr.IsA <DeltaStateEvent>()) { return; } // Fetch device. var device = InputSystem.GetDeviceById(eventPtr.deviceId); if (device == null) { return; } // Go through controls and see if there's anything interesting in the event. var controls = device.allControls; var controlCount = controls.Count; var haveChangedCandidates = false; for (var i = 0; i < controlCount; ++i) { var control = controls[i]; // Skip controls that have no state in the event. var statePtr = control.GetStatePtrFromStateEvent(eventPtr); if (statePtr == null) { continue; } // If the control that cancels has been actuated, abort the operation now. if (!string.IsNullOrEmpty(m_CancelBinding) && InputControlPath.Matches(m_CancelBinding, control) && !control.CheckStateIsAtDefault(statePtr) && control.HasValueChangeInState(statePtr)) { OnCancel(); break; } // Skip noisy controls. if (control.noisy && (m_Flags & Flags.DontIgnoreNoisyControls) == 0) { continue; } // If controls have to match a certain path, check if this one does. if (m_IncludePathCount > 0 && !HavePathMatch(control, m_IncludePaths, m_IncludePathCount)) { continue; } // If controls must not match certain path, make sure the control doesn't. if (m_ExcludePathCount > 0 && HavePathMatch(control, m_ExcludePaths, m_ExcludePathCount)) { continue; } // If we're expecting controls of a certain type, skip if control isn't of // the right type. if (m_ControlType != null && !m_ControlType.IsInstanceOfType(control)) { continue; } // If we're expecting controls to be based on a specific layout, skip if control // isn't based on that layout. if (!m_ExpectedLayout.IsEmpty() && m_ExpectedLayout != control.m_Layout && !InputControlLayout.s_Layouts.IsBasedOn(m_ExpectedLayout, control.m_Layout)) { continue; } // Skip controls that are in their default state. // NOTE: This is the cheapest check with respect to looking at actual state. So // do this first before looking further at the state. if (control.CheckStateIsAtDefault(statePtr)) { continue; } // Skip controls that have no effective value change. // NOTE: This will run the full processor stack and is more involved. if (!control.HasValueChangeInState(statePtr)) { continue; } // If we have a magnitude threshold, see if control passes it. var magnitude = -1f; if (m_MagnitudeThreshold >= 0f) { magnitude = control.EvaluateMagnitude(statePtr); if (magnitude >= 0 && magnitude < m_MagnitudeThreshold) { continue; // No, so skip. } } // Compute score. float score; if (m_OnComputeScore != null) { score = m_OnComputeScore(control, eventPtr); } else { score = magnitude; // We don't want synthetic controls to not be bindable at all but they should // generally cede priority to controls that aren't synthetic. So we bump all // scores of controls that aren't synthetic. if (!control.synthetic) { score += 1f; } } // Control is a candidate. // See if we already singled the control out as a potential candidate. var candidateIndex = m_Candidates.IndexOf(control); if (candidateIndex != -1) { // Yes, we did. So just check whether it became a better candidate than before. if (m_Scores[candidateIndex] < score) { haveChangedCandidates = true; m_Scores[candidateIndex] = score; if (m_WaitSecondsAfterMatch > 0) { m_LastMatchTime = InputRuntime.s_Instance.currentTime; } } } else { // No, so add it. var candidateCount = m_Candidates.Count; m_Candidates.Add(control); ArrayHelpers.AppendWithCapacity(ref m_Scores, ref candidateCount, score); haveChangedCandidates = true; if (m_WaitSecondsAfterMatch > 0) { m_LastMatchTime = InputRuntime.s_Instance.currentTime; } } } if (haveChangedCandidates && !canceled) { // If we have a callback that wants to control matching, leave it to the callback to decide // whether the rebind is complete or not. Otherwise, just complete. if (m_OnPotentialMatch != null) { SortCandidatesByScore(); m_OnPotentialMatch(this); } else if (m_WaitSecondsAfterMatch <= 0) { OnComplete(); } else { SortCandidatesByScore(); } } }
public void OnEventTimestampOutdated(InputEventPtr eventPtr, InputDevice device) { Debug.LogError(string.Format("'{0}' input event for device '{1}' is outdated (event time: {2}, device time: {3})", eventPtr.type, device, eventPtr.time, device.lastUpdateTime)); }
private void SetupInputControl() { Debug.Assert(m_Control == null); Debug.Assert(m_NextControlOnDevice == null); Debug.Assert(!m_InputEventPtr.valid); // Nothing to do if we don't have a control path. if (string.IsNullOrEmpty(m_ControlPath)) { return; } // Determine what type of device to work with. var layoutName = InputControlPath.TryGetDeviceLayout(m_ControlPath); if (layoutName == null) { Debug.LogError( string.Format( "Cannot determine device layout to use based on control path '{0}' used in {1} component", m_ControlPath, GetType().Name), this); return; } // Try to find existing on-screen device that matches. var internedLayoutName = new InternedString(layoutName); var deviceInfoIndex = -1; for (var i = 0; i < s_OnScreenDevices.length; ++i) { if (s_OnScreenDevices[i].device.m_Layout == internedLayoutName) { deviceInfoIndex = i; break; } } // If we don't have a matching one, create a new one. InputDevice device; if (deviceInfoIndex == -1) { // Try to create device. try { device = InputSystem.AddDevice(layoutName); } catch (Exception exception) { Debug.LogError(string.Format("Could not create device with layout '{0}' used in '{1}' component", layoutName, GetType().Name)); Debug.LogException(exception); return; } // Create event buffer. InputEventPtr eventPtr; var buffer = StateEvent.From(device, out eventPtr, Allocator.Persistent); // Add to list. deviceInfoIndex = s_OnScreenDevices.Append(new OnScreenDeviceInfo { eventPtr = eventPtr, buffer = buffer, device = device, }); } else { device = s_OnScreenDevices[deviceInfoIndex].device; } // Try to find control on device. m_Control = InputControlPath.TryFindControl(device, m_ControlPath); if (m_Control == null) { Debug.LogError( string.Format( "Cannot find control with path '{0}' on device of type '{1}' referenced by component '{2}'", m_ControlPath, layoutName, GetType().Name), this); // Remove the device, if we just created one. if (s_OnScreenDevices[deviceInfoIndex].firstControl == null) { s_OnScreenDevices[deviceInfoIndex].Destroy(); s_OnScreenDevices.RemoveAt(deviceInfoIndex); } return; } m_InputEventPtr = s_OnScreenDevices[deviceInfoIndex].eventPtr; // We have all we need. Permanently add us. s_OnScreenDevices[deviceInfoIndex] = s_OnScreenDevices[deviceInfoIndex].AddControl(this); }
bool IEventMerger.MergeForward(InputEventPtr currentEventPtr, InputEventPtr nextEventPtr) { return(MergeForward(currentEventPtr, nextEventPtr)); }
public static void WriteValueIntoEvent <TValue>(this InputControl control, TValue value, InputEventPtr eventPtr) where TValue : struct { if (control == null) { throw new ArgumentNullException("control"); } if (!eventPtr.valid) { throw new ArgumentNullException("eventPtr"); } var controlOfType = control as InputControl <TValue>; if (controlOfType == null) { throw new ArgumentException(string.Format("Expecting control of type '{0}' but got '{1}'", typeof(TValue).Name, control.GetType().Name)); } controlOfType.WriteValueIntoEvent(value, eventPtr); }
public void OnEventForDisabledDevice(InputEventPtr eventPtr, InputDevice device) { Debug.LogError($"Device '{device}' received input event '{eventPtr}' but the device is disabled"); }
/// <summary> /// Read the value for the given control from the given event. /// </summary> /// <param name="control">Control to read value for.</param> /// <param name="inputEvent">Event to read value from. Must be a <see cref="StateEvent"/> or <see cref="DeltaStateEvent"/>.</param> /// <typeparam name="TValue">Type of value to read.</typeparam> /// <exception cref="ArgumentNullException"><paramref name="control"/> is <c>null</c>.</exception> /// <exception cref="ArgumentException"><paramref name="inputEvent"/> is not a <see cref="StateEvent"/> or <see cref="DeltaStateEvent"/>.</exception> /// <returns>The value for the given control as read out from the given event or <c>default(TValue)</c> if the given /// event does not contain a value for the control (e.g. if it is a <see cref="DeltaStateEvent"/> not containing the relevant /// portion of the device's state memory).</returns> public static TValue ReadValueFromEvent <TValue>(this InputControl <TValue> control, InputEventPtr inputEvent) where TValue : struct { if (control == null) { throw new ArgumentNullException(nameof(control)); } if (!ReadValueFromEvent(control, inputEvent, out var value)) { return(default);
public void OnCannotFindDeviceForEvent(InputEventPtr eventPtr) { Debug.LogError("Cannot find device for input event: " + eventPtr); }
protected static unsafe void Accumulate(InputControl <float> control, void *oldStatePtr, InputEventPtr newState) { if (control == null) { throw new ArgumentNullException(nameof(control)); } if (!control.ReadUnprocessedValueFromEvent(newState, out var newDelta)) { return; // Value for the control not contained in the given event. } var oldDelta = control.ReadUnprocessedValueFromState(oldStatePtr); control.WriteValueIntoEvent(oldDelta + newDelta, newState); }
/// <summary> /// Called when the pointer receives a state event. /// </summary> /// <param name="eventPtr">The input event.</param> protected unsafe void OnStateEvent(InputEventPtr eventPtr) { ////FIXME: This stuff makes pointer events too expensive; find a better way. delta.AccumulateValueInEvent(currentStatePtr, eventPtr); InputState.Change(this, eventPtr); }
/// <summary> /// Checks an Input Event for any significant changes that would be considered user activity. /// </summary> /// <param name="inputEvent">The input event being checked for changes</param> /// <param name="device">The input device being checked against </param> /// <param name="offset">The offset into the device that the event is placed</param> /// <param name="sizeInBytes">The size of the event in bytes</param> /// <returns>True if any changes exist in the event once the device has been filtered through for noise and non-significant changes. False otherwise.</returns> public unsafe bool EventHasValidData(InputDevice device, InputEventPtr inputEvent, uint offset, uint sizeInBytes) { if (!inputEvent.valid) { throw new ArgumentException("Invalid or unset event being checked.", "inputEvent"); } if (device == null) { throw new ArgumentNullException("device"); } if (IsEmpty()) { return(true); } if ((offset + sizeInBytes) * 8 > device.stateBlock.sizeInBits) { return(false); } var noiseFilterPtr = InputStateBuffers.s_NoiseBitmaskBuffer; if (noiseFilterPtr == IntPtr.Zero) { throw new Exception("Noise Filter Buffer is uninitialized while trying to check state events for data."); } var ptrToEventState = IntPtr.Zero; if (inputEvent.IsA <StateEvent>()) { var stateEvent = StateEvent.From(inputEvent); ptrToEventState = stateEvent->state; } else if (inputEvent.IsA <DeltaStateEvent>()) { var stateEvent = DeltaStateEvent.From(inputEvent); ptrToEventState = stateEvent->deltaState; } else { throw new ArgumentException(string.Format( "Invalid event type '{0}', we can only check for valid data on StateEvents and DeltaStateEvents.", inputEvent.type), "inputEvent"); } if (MemoryHelpers.HasAnyNonZeroBitsAfterMaskingWithBuffer(ptrToEventState, noiseFilterPtr, offset, sizeInBytes * 8)) { return(true); } for (var i = 0; i < elements.Length; i++) { if (elements[i].EventHasValidData(inputEvent, device)) { return(true); } } return(false); }
void IInputStateCallbackReceiver.OnStateEvent(InputEventPtr eventPtr) { OnStateEvent(eventPtr); }
protected void OnSourceControlChangedValue(InputControl control, double time, InputEventPtr eventPtr, long sourceDeviceAndButtonIndex) { var sourceDeviceIndex = sourceDeviceAndButtonIndex & 0xffffffff; if (sourceDeviceIndex < 0 && sourceDeviceIndex >= m_NumSources) { throw new ArgumentOutOfRangeException(nameof(sourceDeviceIndex), $"Index {sourceDeviceIndex} out of range; have {m_NumSources} sources"); } ////TODO: this can be simplified a lot if we use events instead of InputState.Change() but doing so requires work on buffering events while processing; also //// needs extra handling to not lag into the next frame if (control is ButtonControl button) { var buttonIndex = (int)(sourceDeviceAndButtonIndex >> 32); var isPressed = button.isPressed; if (isPressed) { // Start new touch. for (var i = 0; i < m_Touches.Length; ++i) { // Find unused touch. if (m_Touches[i].touchId != 0) { continue; } var touchId = ++m_LastTouchId; m_Touches[i] = new SimulatedTouch { touchId = touchId, buttonIndex = buttonIndex, sourceIndex = (int)sourceDeviceIndex, }; var isPrimary = m_PrimaryTouchIndex == -1; var position = m_CurrentPositions[sourceDeviceIndex]; var oldTouch = simulatedTouchscreen.touches[i].ReadValue(); var touch = new TouchState { touchId = touchId, position = position, phase = TouchPhase.Began, startTime = time, startPosition = position, isPrimaryTouch = isPrimary, tapCount = oldTouch.tapCount, }; if (isPrimary) { InputState.Change(simulatedTouchscreen.primaryTouch, touch, eventPtr: eventPtr); m_PrimaryTouchIndex = i; } InputState.Change(simulatedTouchscreen.touches[i], touch, eventPtr: eventPtr); break; } } else { // End ongoing touch. for (var i = 0; i < m_Touches.Length; ++i) { if (m_Touches[i].buttonIndex != buttonIndex || m_Touches[i].sourceIndex != sourceDeviceIndex || m_Touches[i].touchId == 0) { continue; } // Detect taps. var position = m_CurrentPositions[sourceDeviceIndex]; var oldTouch = simulatedTouchscreen.touches[i].ReadValue(); var isTap = time - oldTouch.startTime <= Touchscreen.s_TapTime && (position - oldTouch.startPosition).sqrMagnitude <= Touchscreen.s_TapRadiusSquared; var touch = new TouchState { touchId = m_Touches[i].touchId, phase = TouchPhase.Ended, position = position, tapCount = (byte)(oldTouch.tapCount + (isTap ? 1 : 0)), isTap = isTap, startPosition = oldTouch.startPosition, startTime = oldTouch.startTime, }; if (m_PrimaryTouchIndex == i) { InputState.Change(simulatedTouchscreen.primaryTouch, touch, eventPtr: eventPtr); ////TODO: check if there's an ongoing touch that can take over m_PrimaryTouchIndex = -1; } InputState.Change(simulatedTouchscreen.touches[i], touch, eventPtr: eventPtr); m_Touches[i].touchId = 0; break; } } } else { Debug.Assert(control is InputControl <Vector2>, "Expecting control to be either a button or a position"); var positionControl = (InputControl <Vector2>)control; // Update recorded position. var position = positionControl.ReadValue(); var delta = position - m_CurrentPositions[sourceDeviceIndex]; m_CurrentPositions[sourceDeviceIndex] = position; // Update position of ongoing touches from this pointer. for (var i = 0; i < m_Touches.Length; ++i) { if (m_Touches[i].sourceIndex != sourceDeviceIndex || m_Touches[i].touchId == 0) { continue; } var oldTouch = simulatedTouchscreen.touches[i].ReadValue(); var isPrimary = m_PrimaryTouchIndex == i; var touch = new TouchState { touchId = m_Touches[i].touchId, phase = TouchPhase.Moved, position = position, delta = delta, isPrimaryTouch = isPrimary, tapCount = oldTouch.tapCount, isTap = false, // Can't be tap as it's a move. startPosition = oldTouch.startPosition, startTime = oldTouch.startTime, }; if (isPrimary) { InputState.Change(simulatedTouchscreen.primaryTouch, touch, eventPtr: eventPtr); } InputState.Change(simulatedTouchscreen.touches[i], touch, eventPtr: eventPtr); } } }
/// <inheritdoc cref="IRLActionInputAdaptor.WriteToInputEventForAction"/> public void WriteToInputEventForAction(InputEventPtr eventPtr, InputAction action, InputControl control, ActionSpec actionSpec, in ActionBuffers actionBuffers)
void IInputStateChangeMonitor.NotifyControlStateChanged(InputControl control, double time, InputEventPtr eventPtr, long monitorIndex) { OnSourceControlChangedValue(control, time, eventPtr, monitorIndex); }
public static unsafe bool ReadUnprocessedValueFromEvent <TValue>(this InputControl <TValue> control, InputEventPtr inputEvent, out TValue value) where TValue : struct { if (control == null) { throw new ArgumentNullException(nameof(control)); } var statePtr = control.GetStatePtrFromStateEvent(inputEvent); if (statePtr == null) { value = control.ReadDefaultValue(); return(false); } value = control.ReadUnprocessedValueFromState(statePtr); return(true); }
public void OnEventTimestampOutdated(InputEventPtr eventPtr, InputDevice device) { Debug.LogError( $"'{eventPtr.type}' input event for device '{device}' is outdated (event time: {eventPtr.time}, device time: {device.lastUpdateTime})"); }
public static void WriteValueIntoEvent <TValue>(this InputControl control, TValue value, InputEventPtr eventPtr) where TValue : struct { if (control == null) { throw new ArgumentNullException(nameof(control)); } if (!eventPtr.valid) { throw new ArgumentNullException(nameof(eventPtr)); } if (!(control is InputControl <TValue> controlOfType)) { throw new ArgumentException( $"Expecting control of type '{typeof(TValue).Name}' but got '{control.GetType().Name}'"); } controlOfType.WriteValueIntoEvent(value, eventPtr); }
public void OnEventFormatMismatch(InputEventPtr eventPtr, InputDevice device) { Debug.LogError( $"'{eventPtr.type}' input event for device '{device}' has incorrect format (event format: '{eventPtr.type}', device format: '{device.stateBlock.format}')"); }
public static unsafe void *GetStatePtrFromStateEvent(this InputControl control, InputEventPtr eventPtr) { if (control == null) { throw new ArgumentNullException(nameof(control)); } if (!eventPtr.valid) { throw new ArgumentNullException(nameof(eventPtr)); } uint stateOffset; FourCC stateFormat; uint stateSizeInBytes; void * statePtr; if (eventPtr.IsA <DeltaStateEvent>()) { var deltaEvent = DeltaStateEvent.From(eventPtr); // If it's a delta event, we need to subtract the delta state offset if it's not set to the root of the device stateOffset = deltaEvent->stateOffset; stateFormat = deltaEvent->stateFormat; stateSizeInBytes = deltaEvent->deltaStateSizeInBytes; statePtr = deltaEvent->deltaState; } else if (eventPtr.IsA <StateEvent>()) { var stateEvent = StateEvent.From(eventPtr); stateOffset = 0; stateFormat = stateEvent->stateFormat; stateSizeInBytes = stateEvent->stateSizeInBytes; statePtr = stateEvent->state; } else { throw new ArgumentException("Event must be a state or delta state event", "eventPtr"); } // Make sure we have a state event compatible with our device. The event doesn't // have to be specifically for our device (we don't require device IDs to match) but // the formats have to match and the size must be within range of what we're trying // to read. var device = control.device; if (stateFormat != device.m_StateBlock.format) { throw new InvalidOperationException( $"Cannot read control '{control.path}' from {eventPtr.type} with format {stateFormat}; device '{device}' expects format {device.m_StateBlock.format}"); } // Once a device has been added, global state buffer offsets are baked into control hierarchies. // We need to unsubtract those offsets here. stateOffset += device.m_StateBlock.byteOffset; // Return null if state is out of range. var controlOffset = (int)control.m_StateBlock.byteOffset - stateOffset; if (controlOffset < 0 || controlOffset + control.m_StateBlock.alignedSizeInBytes > stateSizeInBytes) { return(null); } return((byte *)statePtr - (int)stateOffset); }
private void UnpairedDeviceUsed(InputControl control, InputEventPtr eventPtr) { if (!(control is ButtonControl) || control.device.displayName == "Keyboard" || control.device.displayName == "Mouse") { return; } Debug.Log("Device: " + control.device.displayName); InputUser user = InputUser.PerformPairingWithDevice(control.device); PlayerControls controlsForUser = new PlayerControls(); user.AssociateActionsWithUser(controlsForUser); controlsForUser.Enable(); if (players.Count == 0) { player1.GetComponent <Movement>().BindControls(controlsForUser); player1.SetActive(true); player1.transform.position = spawnPoint1.transform.position; players.Add(player1.GetComponent <Movement>()); GetComponent <Deathcount>().player1Deaths = 0; } else if (players.Count == 1) { player2.GetComponent <Movement>().BindControls(controlsForUser); player2.SetActive(true); player2.transform.position = spawnPoint2.transform.position; players.Add(player2.GetComponent <Movement>()); GetComponent <Deathcount>().player2Deaths = 0; } else if (players.Count == 2) { player3.GetComponent <Movement>().BindControls(controlsForUser); player3.SetActive(true); player3.transform.position = spawnPoint3.transform.position; players.Add(player3.GetComponent <Movement>()); GetComponent <Deathcount>().player3Deaths = 0; } else if (players.Count == 3) { player4.GetComponent <Movement>().BindControls(controlsForUser); player4.SetActive(true); player4.transform.position = spawnPoint4.transform.position; players.Add(player4.GetComponent <Movement>()); GetComponent <Deathcount>().player4Deaths = 0; } List <GameObject> tempPlayers = new List <GameObject>(); foreach (var item in players) { tempPlayers.Add(item.gameObject); } InputUser.listenForUnpairedDeviceActivity--; if (InputUser.listenForUnpairedDeviceActivity == 0) { StopJoining(); } }