Пример #1
0
        /// <summary>
        /// Set the control to the given value by sending a state event with the value to the
        /// control's device.
        /// </summary>
        /// <param name="control">An input control on a device that has been added to the system.</param>
        /// <param name="state">New value for the input control.</param>
        /// <typeparam name="TValue">Value type of the given control.</typeparam>
        /// <example>
        /// <code>
        /// var gamepad = InputSystem.AddDevice&lt;Gamepad&gt;();
        /// Set(gamepad.leftButton, 1);
        /// </code>
        /// </example>
        public void Set <TValue>(InputControl <TValue> control, TValue state, double absoluteTime = -1, double timeOffset = 0)
            where TValue : struct
        {
            if (control == null)
            {
                throw new ArgumentNullException(nameof(control));
            }
            if (!control.device.added)
            {
                throw new ArgumentException(
                          $"Device of control '{control}' has not been added to the system", nameof(control));
            }

            using (StateEvent.From(control.device, out var eventPtr))
            {
                ////REVIEW: should we by default take the time from the device here?
                if (absoluteTime >= 0)
                {
                    eventPtr.time = absoluteTime;
                }
                eventPtr.time += timeOffset;
                control.WriteValueIntoEvent(state, eventPtr);
                InputSystem.QueueEvent(eventPtr);
            }

            InputSystem.Update();
        }
Пример #2
0
        /// <summary>
        /// Set the control to the given value by sending a state event with the value to the
        /// control's device.
        /// </summary>
        /// <param name="control">An input control on a device that has been added to the system.</param>
        /// <param name="state">New value for the input control.</param>
        /// <param name="time">Timestamp to use for the state event. If -1 (default), current time is used (see <see cref="InputTestFixture.currentTime"/>).</param>
        /// <param name="timeOffset">Offset to apply to the current time. This is an alternative to <paramref name="time"/>. By default, no offset is applied.</param>
        /// <param name="queueEventOnly">If true, no <see cref="InputSystem.Update"/> will be performed after queueing the event. This will only put
        /// the state event on the event queue and not do anything else. The default is to call <see cref="InputSystem.Update"/> after queuing the event.
        /// Note that not issuing an update means the state of the device will not change yet. This may affect subsequent Set/Press/Release/etc calls
        /// as they will not yet see the state change.
        ///
        /// Note that this parameter will be ignored if the test is a <c>[UnityTest]</c>. Multi-frame
        /// playmode tests will automatically process input as part of the Unity player loop.</param>
        /// <typeparam name="TValue">Value type of the given control.</typeparam>
        /// <example>
        /// <code>
        /// var gamepad = InputSystem.AddDevice&lt;Gamepad&gt;();
        /// Set(gamepad.leftButton, 1);
        /// </code>
        /// </example>
        public void Set <TValue>(InputControl <TValue> control, TValue state, double time = -1, double timeOffset = 0, bool queueEventOnly = false)
            where TValue : struct
        {
            if (control == null)
            {
                throw new ArgumentNullException(nameof(control));
            }
            if (!control.device.added)
            {
                throw new ArgumentException(
                          $"Device of control '{control}' has not been added to the system", nameof(control));
            }

            if (IsUnityTest())
            {
                queueEventOnly = true;
            }

            void SetUpAndQueueEvent(InputEventPtr eventPtr)
            {
                ////REVIEW: should we by default take the time from the device here?
                if (time >= 0)
                {
                    eventPtr.time = time;
                }
                eventPtr.time += timeOffset;
                control.WriteValueIntoEvent(state, eventPtr);
                InputSystem.QueueEvent(eventPtr);
            }

            // Touchscreen does not support delta events involving TouchState.
            if (control is TouchControl)
            {
                using (StateEvent.From(control.device, out var eventPtr))
                    SetUpAndQueueEvent(eventPtr);
            }
            else
            {
                // We use delta state events rather than full state events here to mitigate the following problem:
                // Grabbing state from the device will preserve the current values of controls covered in the state.
                // However, running an update may alter the value of one or more of those controls. So with a full
                // state event, we may be writing outdated data back into the device. For example, in the case of delta
                // controls which will reset in OnBeforeUpdate().
                //
                // Using delta events, we may still grab state outside of just the one control in case we're looking at
                // bit-addressed controls but at least we can avoid the problem for the majority of controls.
                using (DeltaStateEvent.From(control, out var eventPtr))
                    SetUpAndQueueEvent(eventPtr);
            }

            if (!queueEventOnly)
            {
                InputSystem.Update();
            }
        }
Пример #3
0
        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);
        }
Пример #4
0
        /// <summary>
        /// Queue a value change on the given <paramref name="control"/> which will be processed and take effect
        /// in the next input update.
        /// </summary>
        /// <param name="control">Control to change the value of.</param>
        /// <param name="value">New value for the control.</param>
        /// <param name="time">Optional time at which the value change should take effect. If set, this will become
        /// the <see cref="InputEvent.time"/> of the queued event. If the time is in the future, the event will not
        /// be processed until it falls within the time of an input update slice (except if <see cref="InputSettings.timesliceEvents"/>
        /// is false, in which case the event will invariably be consumed in the next update).</param>
        /// <typeparam name="TValue">Type of value.</typeparam>
        /// <exception cref="ArgumentNullException"><paramref name="control"/> is null.</exception>
        public static void QueueValueChange <TValue>(this InputControl <TValue> control, TValue value, double time = -1)
            where TValue : struct
        {
            if (control == null)
            {
                throw new ArgumentNullException(nameof(control));
            }

            ////TODO: if it's not a bit-addressing control, send a delta state change only
            using (StateEvent.From(control.device, out var eventPtr))
            {
                if (time >= 0)
                {
                    eventPtr.time = time;
                }
                control.WriteValueIntoEvent(value, eventPtr);
                InputSystem.QueueEvent(eventPtr);
            }
        }