public void Events_CanCreateDeltaStateEventFromControl()
    {
        var gamepad = InputSystem.AddDevice <Gamepad>();

        Set(gamepad.buttonSouth, 1);
        Set(gamepad.buttonNorth, 1);
        Set(gamepad.leftTrigger, 0.123f);

        using (DeltaStateEvent.From(gamepad.buttonNorth, out var eventPtr))
        {
            Assert.That(gamepad.buttonNorth.ReadValueFromEvent(eventPtr, out var val), Is.True);
            Assert.That(val, Is.EqualTo(1).Within(0.00001));

            gamepad.buttonNorth.WriteValueIntoEvent(0f, eventPtr);

            InputSystem.QueueEvent(eventPtr);
            InputSystem.Update();

            Assert.That(gamepad.buttonNorth.ReadValue(), Is.Zero);
        }
    }
    public void Controls_DisplayNameDefaultsToControlName()
    {
        const string json = @"
            {
                ""name"" : ""MyDevice"",
                ""controls"" : [
                    {
                        ""name"" : ""control"",
                        ""layout"" : ""Button""
                    }
                ]
            }
        ";

        InputSystem.RegisterLayout(json);

        var control = InputDevice.Build <InputDevice>("MyDevice")["control"];

        Assert.That(control.displayName, Is.EqualTo("control"));
        Assert.That(control.shortDisplayName, Is.Null);
    }
Beispiel #3
0
    public void Controls_DisplayNameDefaultsToControlName()
    {
        const string json = @"
            {
                ""name"" : ""MyDevice"",
                ""controls"" : [
                    {
                        ""name"" : ""control"",
                        ""layout"" : ""Button""
                    }
                ]
            }
        ";

        InputSystem.RegisterLayout(json);

        var setup   = new InputDeviceBuilder("MyDevice");
        var control = setup.GetControl("control");

        Assert.That(control.displayName, Is.EqualTo("control"));
    }
    public void Events_EventBuffer_CanAddEvents()
    {
        var gamepad = InputSystem.AddDevice <Gamepad>();

        unsafe
        {
            using (StateEvent.From(gamepad, out var eventPtr))
                using (var buffer = new InputEventBuffer())
                {
                    // Write two events into buffer.
                    gamepad.leftStick.WriteValueIntoEvent(Vector2.one, eventPtr);
                    eventPtr.id      = 111;
                    eventPtr.time    = 123;
                    eventPtr.handled = false;
                    buffer.AppendEvent(eventPtr);
                    gamepad.leftStick.WriteValueIntoEvent(Vector2.zero, eventPtr);
                    eventPtr.id      = 222;
                    eventPtr.time    = 234;
                    eventPtr.handled = true;
                    buffer.AppendEvent(eventPtr);

                    Assert.That(buffer.eventCount, Is.EqualTo(2));
                    var events = buffer.ToArray();

                    Assert.That(events, Has.Length.EqualTo(2));
                    Assert.That(events[0].type, Is.EqualTo(new FourCC(StateEvent.Type)));
                    Assert.That(events[1].type, Is.EqualTo(new FourCC(StateEvent.Type)));
                    Assert.That(events[0].time, Is.EqualTo(123).Within(0.00001));
                    Assert.That(events[1].time, Is.EqualTo(234).Within(0.00001));
                    Assert.That(events[0].id, Is.EqualTo(111));
                    Assert.That(events[1].id, Is.EqualTo(222));
                    Assert.That(events[0].handled, Is.False);
                    Assert.That(events[1].handled, Is.True);
                    Assert.That(events[0].deviceId, Is.EqualTo(gamepad.id));
                    Assert.That(events[1].deviceId, Is.EqualTo(gamepad.id));
                    Assert.That(InputControlExtensions.ReadUnprocessedValueFromEvent(gamepad.leftStick, events[0]), Is.EqualTo(Vector2.one));
                    Assert.That(InputControlExtensions.ReadUnprocessedValueFromEvent(gamepad.leftStick, events[1]), Is.EqualTo(Vector2.zero));
                }
        }
    }
Beispiel #5
0
        public void BAD_AccessStructKey()
        {
            var cache = new Dictionary <Data, int>();

            for (int i = 0; i < ELEM_COUNT; ++i)
            {
                cache.Add(new Data(i, i), i);
            }

            Assert.That(() =>
            {
                int v = 0;
                for (int j = 0; j < ELEM_COUNT; ++j)
                {
                    v += cache[new Data(j, j)];
                }
            },
                        Is.AllocatingGCMemory()
                        );


            // GC.Collect();
            // long startMem = Profiler.GetMonoUsedSizeLong();

            // //------------------//
            // for(int i=0; i<LOOP_COUNT; ++i)
            // {
            //     cont.Clear();
            //     for(int j=0; j<ELEM_COUNT; ++j)
            //     {
            //         cont.Add(cache[new Data(j,j)]);
            //     }
            // }

            // long mem1 = Profiler.GetMonoUsedSizeLong();
            // Assert.That(mem1, Is.GreaterThan(startMem));

            // //------------------//
            // Debug.Log(string.Format("startMem = {0}, mem1 = {1}", startMem, mem1));
        }
    public void Controls_CanReadValueFromStateEvents()
    {
        var gamepad = InputSystem.AddDevice <Gamepad>();

        var receivedCalls = 0;

        InputSystem.onEvent +=
            eventPtr =>
        {
            ++receivedCalls;
            float value;
            Assert.IsTrue(gamepad.leftTrigger.ReadValueFromEvent(eventPtr, out value));
            Assert.That(value, Is.EqualTo(0.234f).Within(0.00001));
        };

        InputSystem.QueueStateEvent(gamepad, new GamepadState {
            leftTrigger = 0.234f
        });
        InputSystem.Update();

        Assert.That(receivedCalls, Is.EqualTo(1));
    }
    public void Events_AreProcessedInBothFixedAndDynamicUpdateByDefault()
    {
        var mouse = InputSystem.AddDevice <Mouse>();

        Assert.That(InputSystem.settings.updateMode, Is.EqualTo(InputSettings.UpdateMode.ProcessEventsInBothFixedAndDynamicUpdate));
        Assert.That(InputSystem.s_Manager.m_StateBuffers.GetDoubleBuffersFor(InputUpdateType.Fixed).valid, Is.True);
        Assert.That(InputSystem.s_Manager.m_StateBuffers.GetDoubleBuffersFor(InputUpdateType.Dynamic).valid, Is.True);
        Assert.That(InputSystem.s_Manager.m_StateBuffers.GetDoubleBuffersFor(InputUpdateType.Manual).valid, Is.False);

        // Push event through in fixed update.
        InputSystem.QueueStateEvent(mouse, new MouseState().WithButton(MouseButton.Left));
        InputSystem.Update(InputUpdateType.Fixed);

        Assert.That(mouse.leftButton.isPressed, Is.True);

        // Push event through in dynamic update.
        InputSystem.QueueStateEvent(mouse, new MouseState().WithButton(MouseButton.Right));
        InputSystem.Update(InputUpdateType.Dynamic);

        Assert.That(mouse.leftButton.isPressed, Is.False);
        Assert.That(mouse.rightButton.isPressed, Is.True);
    }
    public void Controls_CanHaveStickDeadzones()
    {
        const string json = @"
            {
                ""name"" : ""MyDevice"",
                ""extend"" : ""Gamepad"",
                ""controls"" : [
                    {
                        ""name"" : ""leftStick"",
                        ""processors"" : ""stickDeadzone(min=0.1,max=0.9)""
                    }
                ]
            }
        ";

        InputSystem.RegisterLayout(json);
        var device = (Gamepad)InputSystem.AddDevice("MyDevice");

        ////NOTE: Unfortunately, this relies on an internal method ATM.
        var processor = device.leftStick.TryGetProcessor <StickDeadzoneProcessor>();

        var firstState = new GamepadState {
            leftStick = new Vector2(0.05f, 0.05f)
        };
        var secondState = new GamepadState {
            leftStick = new Vector2(0.5f, 0.5f)
        };

        InputSystem.QueueStateEvent(device, firstState);
        InputSystem.Update();

        Assert.That(device.leftStick.ReadValue(), Is.EqualTo(default(Vector2)));

        InputSystem.QueueStateEvent(device, secondState);
        InputSystem.Update();

        Assert.That(device.leftStick.ReadValue(),
                    Is.EqualTo(processor.Process(new Vector2(0.5f, 0.5f), device.leftStick)));
    }
    public void Controls_ReadingValueFromStateEvent_ReturnsDefaultValueForControlsNotPartOfEvent()
    {
        // Add one extra control with default state to Gamepad but
        // don't change its state format (so we can send it GamepadState
        // events without the extra control).
        const string json = @"
            {
                ""name"" : ""TestDevice"",
                ""extend"" : ""Gamepad"",
                ""controls"" : [
                    {
                        ""name"" : ""extraControl"",
                        ""layout"" : ""Axis"",
                        ""defaultState"" : ""0.1234""
                    }
                ]
            }
        ";

        InputSystem.RegisterLayout(json);
        var device = InputSystem.AddDevice("TestDevice");

        float?value = null;

        InputSystem.onEvent +=
            eventPtr =>
        {
            Assert.That(value, Is.Null);
            float eventValue;
            ((AxisControl)device["extraControl"]).ReadValueFromEvent(eventPtr, out eventValue);
            value = eventValue;
        };

        InputSystem.QueueStateEvent(device, new GamepadState());
        InputSystem.Update();

        Assert.That(value, Is.Not.Null);
        Assert.That(value.Value, Is.EqualTo(0.1234).Within(0.00001));
    }
    public void Events_SendingStateToDeviceWithBeforeRenderEnabled_UpdatesDeviceInBeforeRender()
    {
        const string deviceJson = @"
            {
                ""name"" : ""CustomGamepad"",
                ""extend"" : ""Gamepad"",
                ""beforeRender"" : ""Update""
            }
        ";

        InputSystem.RegisterLayout(deviceJson);

        var gamepad  = (Gamepad)InputSystem.AddDevice("CustomGamepad");
        var newState = new GamepadState {
            leftTrigger = 0.123f
        };

        InputSystem.QueueStateEvent(gamepad, newState);
        InputSystem.Update(InputUpdateType.BeforeRender);

        Assert.That(gamepad.leftTrigger.ReadValue(), Is.EqualTo(0.123f).Within(0.000001));
    }
Beispiel #11
0
        public void BAD_SortedList()
        {
            SortedList <int, string> lst = new SortedList <int, string>();

            for (int i = 0; i < ELEM_COUNT; ++i)
            {
                lst.Add(i, i.ToString());
            }

            foreach (var v in lst)
            {
            }                       //warmup

            Assert.That(
                () => {
                int sum = 0;
                foreach (var v in lst)
                {
                    sum += v.Key;
                }
            }, Is.AllocatingGCMemory()
                );
        }
    public void Events_CanQueueAndReceiveEventsAgainstNonExistingDevices()
    {
        // Device IDs are looked up only *after* the system shows the event to us.

        var receivedCalls    = 0;
        var receivedDeviceId = InputDevice.kInvalidDeviceId;

        InputSystem.onEvent +=
            eventPtr =>
        {
            ++receivedCalls;
            receivedDeviceId = eventPtr.deviceId;
        };

        var inputEvent = DeviceConfigurationEvent.Create(4, 1.0);

        InputSystem.QueueEvent(ref inputEvent);

        InputSystem.Update();

        Assert.That(receivedCalls, Is.EqualTo(1));
        Assert.That(receivedDeviceId, Is.EqualTo(4));
    }
    public void Events_CanListenForWhenAllEventsHaveBeenProcessed()
    {
        InputUpdateType?         receivedUpdateType = null;
        Action <InputUpdateType> callback           =
            type =>
        {
            Assert.That(receivedUpdateType, Is.Null);
            receivedUpdateType = type;
        };

        InputSystem.onAfterUpdate += callback;

        InputSystem.Update(InputUpdateType.Dynamic);

        Assert.That(receivedUpdateType, Is.EqualTo(InputUpdateType.Dynamic));

        receivedUpdateType         = null;
        InputSystem.onAfterUpdate -= callback;

        InputSystem.Update();

        Assert.That(receivedUpdateType, Is.Null);
    }
    public void Events_CanSendSmallerStateToDeviceWithLargerState()
    {
        const string json = @"
            {
                ""name"" : ""TestLayout"",
                ""extend"" : ""CustomDevice"",
                ""controls"" : [
                    { ""name"" : ""extra"", ""layout"" : ""Button"" }
                ]
            }
        ";

        InputSystem.RegisterLayout <CustomDevice>();
        InputSystem.RegisterLayout(json);
        var device = (CustomDevice)InputSystem.AddDevice("TestLayout");

        InputSystem.QueueStateEvent(device, new CustomDeviceState {
            axis = 0.5f
        });
        InputSystem.Update();

        Assert.That(device.axis.ReadValue(), Is.EqualTo(0.5).Within(0.000001));
    }
    public unsafe void Controls_CanWriteValueFromObjectIntoState()
    {
        var gamepad = InputSystem.AddDevice <Gamepad>();

        var tempBufferSize = (int)gamepad.stateBlock.alignedSizeInBytes;

        using (var tempBuffer = new NativeArray <byte>(tempBufferSize, Allocator.Temp))
        {
            var tempBufferPtr = (byte *)NativeArrayUnsafeUtility.GetUnsafeReadOnlyPtr(tempBuffer);

            // The device is the first in the system so is guaranteed to start of offset 0 which
            // means we don't need to adjust the pointer here.
            Debug.Assert(gamepad.stateBlock.byteOffset == 0);

            gamepad.leftStick.WriteValueFromObjectIntoState(new Vector2(0.1234f, 0.5678f), tempBufferPtr);

            var leftStickXPtr = (float *)(tempBufferPtr + gamepad.leftStick.x.stateBlock.byteOffset);
            var leftStickYPtr = (float *)(tempBufferPtr + gamepad.leftStick.y.stateBlock.byteOffset);

            Assert.That(*leftStickXPtr, Is.EqualTo(0.1234).Within(0.00001));
            Assert.That(*leftStickYPtr, Is.EqualTo(0.5678).Within(0.00001));
        }
    }
Beispiel #16
0
    public unsafe void Events_CanGetStatePointerFromEventThroughControl_EvenIfDeviceIsStateCallbackReceiver()
    {
        var touchscreen = InputSystem.AddDevice <Touchscreen>();

        using (var trace = new InputEventTrace {
            deviceId = touchscreen.deviceId
        })
        {
            trace.Enable();

            BeginTouch(1, new Vector2(123, 234));

            var statePtr = touchscreen.primaryTouch.position.GetStatePtrFromStateEvent(trace.ToArray()[0]);
            Assert.That(statePtr != null);

            // Attempt reading the position value from the touch event.
            Assert.That(touchscreen.primaryTouch.position.ReadValueFromState(statePtr),
                        Is.EqualTo(new Vector2(123, 234)).Using(Vector2EqualityComparer.Instance));

            // It only works with primaryTouch. See Touchscreen.GetStateOffsetForEvent for details.
            Assert.That(touchscreen.touches[1].position.GetStatePtrFromStateEvent(trace.ToArray()[0]) == null);
        }
    }
        public IEnumerator TestSimpleTaskRoutineStopsStartsWithProviderAndWaiting()
        {
            yield return(null);

            ValueObject result = new ValueObject();

            var runner = new MultiThreadRunner("TestSimpleTaskRoutineStopStartWithProvider");

            {
                bool isCallbackCalled = false;

                var _reusableTaskRoutine = TaskRunner.Instance.AllocateNewTaskRoutine(runner);
                _reusableTaskRoutine.SetEnumeratorProvider(() => SimpleEnumerator(result));
                var continuator = _reusableTaskRoutine
                                  .Start(onStop: () => isCallbackCalled = true);

                Assert.That((continuator as IEnumerator).MoveNext() == true, "can't be completed");
                _reusableTaskRoutine.Stop();

                Thread.Sleep(500); //let's be sure the runner has the time to complete it

                Assert.That((continuator as IEnumerator).MoveNext() == false, "must be completed");
                Assert.True(isCallbackCalled);

                continuator = _reusableTaskRoutine.Start();

                while ((continuator as IEnumerator).MoveNext())
                {
                    yield return(null);
                }
            }

            runner.Dispose();

            Assert.That(result.counter, Is.EqualTo(1));
        }
    public void Events_CanGetAverageEventLag()
    {
        var gamepad  = InputSystem.AddDevice <Gamepad>();
        var keyboard = InputSystem.AddDevice <Keyboard>();

        runtime.advanceTimeEachDynamicUpdate = 0;
        runtime.currentTime = 10;

        InputSystem.QueueStateEvent(keyboard, new KeyboardState(Key.A), 6);
        InputSystem.QueueStateEvent(gamepad, new GamepadState {
            leftStick = new Vector2(0.123f, 0.234f)
        }, 1);
        InputSystem.QueueStateEvent(keyboard, new KeyboardState(Key.A), 10);
        InputSystem.Update();

        InputSystem.QueueStateEvent(gamepad, new GamepadState {
            leftStick = new Vector2(0.234f, 0.345f)
        }, 3);
        InputSystem.Update();

        var metrics = InputSystem.metrics;

        Assert.That(metrics.averageLagTimePerEvent, Is.EqualTo((9 + 7 + 4 + 0) / 4.0).Within(0.0001));
    }
    public void Events_CanSwitchToProcessingInFixedUpdates()
    {
        var mouse = InputSystem.AddDevice <Mouse>();

        var receivedOnChange = true;

        InputSystem.onSettingsChange += () => receivedOnChange = true;

        InputSystem.settings.updateMode = InputSettings.UpdateMode.ProcessEventsInFixedUpdate;

        Assert.That(InputSystem.settings.updateMode, Is.EqualTo(InputSettings.UpdateMode.ProcessEventsInFixedUpdate));
        Assert.That(receivedOnChange, Is.True);
        Assert.That(InputSystem.s_Manager.updateMask & InputUpdateType.Fixed, Is.EqualTo(InputUpdateType.Fixed));
        Assert.That(InputSystem.s_Manager.updateMask & InputUpdateType.Dynamic, Is.EqualTo(InputUpdateType.None));

        InputSystem.QueueStateEvent(mouse, new MouseState().WithButton(MouseButton.Left));
        runtime.currentTimeForFixedUpdate += Time.fixedDeltaTime;
        InputSystem.Update(InputUpdateType.Fixed);

        Assert.That(mouse.leftButton.isPressed, Is.True);

        Assert.That(() => InputSystem.Update(InputUpdateType.Dynamic), Throws.InvalidOperationException);
        Assert.That(() => InputSystem.Update(InputUpdateType.Manual), Throws.InvalidOperationException);
    }
Beispiel #20
0
        public void OK_HashSet_IntersectWith()
        {
            var cont = new HashSet <DummyObjA>();

            cont.UnionWith(_cache);
            cont.Clear();

            GC.Collect();
            long startMem = Profiler.GetMonoUsedSizeLong();

            //------------------//
            for (int i = 0; i < LOOP_COUNT; ++i)
            {
                cont.Clear();
                cont.IntersectWith(_cache);
            }

            long mem1 = Profiler.GetMonoUsedSizeLong();

            Assert.That(mem1, Is.EqualTo(startMem));

            //------------------//
            Debug.Log(string.Format("startMem = {0}, mem1 = {1}", startMem, mem1));
        }
Beispiel #21
0
        public void BAD_HashSet_SymExcept()
        {
            var cont = new HashSet <DummyObjA>();

            cont.UnionWith(_cache);
            cont.Clear();

            GC.Collect();
            long startMem = Profiler.GetMonoUsedSizeLong();

            //------------------//
            for (int i = 0; i < LOOP_COUNT; ++i)
            {
                cont.Clear();
                cont.SymmetricExceptWith(_cache);
            }

            long mem1 = Profiler.GetMonoUsedSizeLong();

            Assert.That(mem1, Is.GreaterThan(startMem));

            //------------------//
            Debug.Log(string.Format("startMem = {0}, mem1 = {1}", startMem, mem1));
        }
    public void Events_UseCurrentTimeByDefault()
    {
        var device = InputSystem.AddDevice <Gamepad>();

        runtime.currentTime = 1234;
        runtime.currentTimeOffsetToRealtimeSinceStartup = 1123;

        double?receivedTime         = null;
        double?receivedInternalTime = null;

        InputSystem.onEvent +=
            (eventPtr, _) =>
        {
            receivedTime         = eventPtr.time;
            receivedInternalTime = eventPtr.internalTime;
        };

        InputSystem.QueueStateEvent(device, new GamepadState());
        InputSystem.Update();

        Assert.That(receivedTime.HasValue, Is.True);
        Assert.That(receivedTime.Value, Is.EqualTo(111).Within(0.00001));
        Assert.That(receivedInternalTime.Value, Is.EqualTo(1234).Within(0.00001));
    }
    public void Controls_SticksProvideAccessToHalfAxes()
    {
        var gamepad = InputSystem.AddDevice <Gamepad>();

        InputSystem.QueueStateEvent(gamepad, new GamepadState {
            leftStick = new Vector2(0.5f, 0.5f)
        });
        InputSystem.Update();

        Assert.That(gamepad.leftStick.up.ReadValue(), Is.EqualTo(0.5).Within(0.000001));
        Assert.That(gamepad.leftStick.down.ReadValue(), Is.EqualTo(0.0).Within(0.000001));
        Assert.That(gamepad.leftStick.right.ReadValue(), Is.EqualTo(0.5).Within(0.000001));
        Assert.That(gamepad.leftStick.left.ReadValue(), Is.EqualTo(0.0).Within(0.000001));

        InputSystem.QueueStateEvent(gamepad, new GamepadState {
            leftStick = new Vector2(-0.5f, -0.5f)
        });
        InputSystem.Update();

        Assert.That(gamepad.leftStick.up.ReadValue(), Is.EqualTo(0.0).Within(0.000001));
        Assert.That(gamepad.leftStick.down.ReadValue(), Is.EqualTo(0.5).Within(0.000001));
        Assert.That(gamepad.leftStick.right.ReadValue(), Is.EqualTo(0.0).Within(0.000001));
        Assert.That(gamepad.leftStick.left.ReadValue(), Is.EqualTo(0.5).Within(0.000001));
    }
    public void Controls_CanHaveAxisDeadzones()
    {
        const string json = @"
            {
                ""name"" : ""MyDevice"",
                ""extend"" : ""Gamepad"",
                ""controls"" : [
                    {
                        ""name"" : ""leftTrigger"",
                        ""processors"" : ""axisDeadzone(min=0.1,max=0.9)""
                    }
                ]
            }
        ";

        InputSystem.RegisterLayout(json);
        var device = (Gamepad)InputSystem.AddDevice("MyDevice");

        ////NOTE: Unfortunately, this relies on an internal method ATM.
        var processor = device.leftTrigger.TryGetProcessor <AxisDeadzoneProcessor>();

        InputSystem.QueueStateEvent(device, new GamepadState {
            leftTrigger = 0.05f
        });
        InputSystem.Update();

        Assert.That(device.leftTrigger.ReadValue(), Is.Zero.Within(0.0001));

        InputSystem.QueueStateEvent(device, new GamepadState {
            leftTrigger = 0.5f
        });
        InputSystem.Update();

        Assert.That(device.leftTrigger.ReadValue(),
                    Is.EqualTo(processor.Process(0.5f, device.leftTrigger)));
    }
 public void Controls_CanTurnControlPathIntoHumanReadableText()
 {
     Assert.That(InputControlPath.ToHumanReadableString("*/{PrimaryAction}"), Is.EqualTo("PrimaryAction [Any]"));
     Assert.That(InputControlPath.ToHumanReadableString("<Gamepad>/leftStick"), Is.EqualTo("leftStick [Gamepad]"));
     Assert.That(InputControlPath.ToHumanReadableString("<Gamepad>/leftStick/x"), Is.EqualTo("leftStick/x [Gamepad]"));
     Assert.That(InputControlPath.ToHumanReadableString("<Gamepad>/leftStick/x"), Is.EqualTo("leftStick/x [Gamepad]"));
     Assert.That(InputControlPath.ToHumanReadableString("<XRController>{LeftHand}/position"), Is.EqualTo("position [LeftHand XRController]"));
     Assert.That(InputControlPath.ToHumanReadableString("*/leftStick"), Is.EqualTo("leftStick [Any]"));
     Assert.That(InputControlPath.ToHumanReadableString("*/{PrimaryMotion}/x"), Is.EqualTo("PrimaryMotion/x [Any]"));
 }
    public void Controls_DpadVectorsAreCircular()
    {
        var gamepad = InputSystem.AddDevice <Gamepad>();

        // Up.
        InputSystem.QueueStateEvent(gamepad, new GamepadState {
            buttons = 1 << (int)GamepadButton.DpadUp
        });
        InputSystem.Update();

        Assert.That(gamepad.dpad.ReadValue(), Is.EqualTo(Vector2.up));

        // Up left.
        InputSystem.QueueStateEvent(gamepad,
                                    new GamepadState
        {
            buttons = 1 << (int)GamepadButton.DpadUp | 1 << (int)GamepadButton.DpadLeft
        });
        InputSystem.Update();

        Assert.That(gamepad.dpad.ReadValue().x, Is.EqualTo((Vector2.up + Vector2.left).normalized.x).Within(0.00001));
        Assert.That(gamepad.dpad.ReadValue().y, Is.EqualTo((Vector2.up + Vector2.left).normalized.y).Within(0.00001));

        // Left.
        InputSystem.QueueStateEvent(gamepad, new GamepadState {
            buttons = 1 << (int)GamepadButton.DpadLeft
        });
        InputSystem.Update();

        Assert.That(gamepad.dpad.ReadValue(), Is.EqualTo(Vector2.left));

        // Down left.
        InputSystem.QueueStateEvent(gamepad,
                                    new GamepadState
        {
            buttons = 1 << (int)GamepadButton.DpadDown | 1 << (int)GamepadButton.DpadLeft
        });
        InputSystem.Update();

        Assert.That(gamepad.dpad.ReadValue().x, Is.EqualTo((Vector2.down + Vector2.left).normalized.x).Within(0.00001));
        Assert.That(gamepad.dpad.ReadValue().y, Is.EqualTo((Vector2.down + Vector2.left).normalized.y).Within(0.00001));

        // Down.
        InputSystem.QueueStateEvent(gamepad, new GamepadState {
            buttons = 1 << (int)GamepadButton.DpadDown
        });
        InputSystem.Update();

        Assert.That(gamepad.dpad.ReadValue(), Is.EqualTo(Vector2.down));

        // Down right.
        InputSystem.QueueStateEvent(gamepad,
                                    new GamepadState
        {
            buttons = 1 << (int)GamepadButton.DpadDown | 1 << (int)GamepadButton.DpadRight
        });
        InputSystem.Update();

        Assert.That(gamepad.dpad.ReadValue().x,
                    Is.EqualTo((Vector2.down + Vector2.right).normalized.x).Within(0.00001));
        Assert.That(gamepad.dpad.ReadValue().y,
                    Is.EqualTo((Vector2.down + Vector2.right).normalized.y).Within(0.00001));

        // Right.
        InputSystem.QueueStateEvent(gamepad, new GamepadState {
            buttons = 1 << (int)GamepadButton.DpadRight
        });
        InputSystem.Update();

        Assert.That(gamepad.dpad.ReadValue(), Is.EqualTo(Vector2.right));

        // Up right.
        InputSystem.QueueStateEvent(gamepad,
                                    new GamepadState
        {
            buttons = 1 << (int)GamepadButton.DpadUp | 1 << (int)GamepadButton.DpadRight
        });
        InputSystem.Update();

        Assert.That(gamepad.dpad.ReadValue().x, Is.EqualTo((Vector2.up + Vector2.right).normalized.x).Within(0.00001));
        Assert.That(gamepad.dpad.ReadValue().y, Is.EqualTo((Vector2.up + Vector2.right).normalized.y).Within(0.00001));
    }
    public void Controls_ReferToTheirDevices()
    {
        var gamepad = InputDevice.Build <Gamepad>();

        Assert.That(gamepad.leftStick.device, Is.SameAs(gamepad));
    }
    public unsafe void Events_AreTimeslicedByDefault()
    {
        runtime.fixedUpdateIntervalInSeconds = 1.0 / 60; // 60 FPS.

        var gamepad = InputSystem.AddDevice <Gamepad>();

        var receivedEvents = new List <InputEvent>();

        InputSystem.onEvent +=
            eventPtr => receivedEvents.Add(*eventPtr.ToPointer());

        // First fixed update should just take everything.
        InputSystem.QueueStateEvent(gamepad, new GamepadState {
            leftTrigger = 0.1234f
        }, 1);
        InputSystem.QueueStateEvent(gamepad, new GamepadState {
            leftTrigger = 0.2345f
        }, 2);
        InputSystem.QueueStateEvent(gamepad, new GamepadState {
            leftTrigger = 0.3456f
        }, 2.9);

        runtime.currentTime = 3;

        InputSystem.Update(InputUpdateType.Fixed);

        Assert.That(receivedEvents, Has.Count.EqualTo(3));
        Assert.That(receivedEvents[0].time, Is.EqualTo(1).Within(0.00001));
        Assert.That(receivedEvents[1].time, Is.EqualTo(2).Within(0.00001));
        Assert.That(receivedEvents[2].time, Is.EqualTo(2.9).Within(0.00001));
        Assert.That(gamepad.leftTrigger.ReadValue(), Is.EqualTo(0.3456).Within(0.00001));

        Assert.That(InputUpdate.s_LastUpdateRetainedEventCount, Is.Zero);
        Assert.That(InputUpdate.s_LastFixedUpdateTime, Is.EqualTo(3).Within(0.0001));

        receivedEvents.Clear();

        // From now on, fixed updates should only take what falls in their slice.
        InputSystem.QueueStateEvent(gamepad, new GamepadState {
            leftTrigger = 0.1234f
        }, 3 + 0.001);
        InputSystem.QueueStateEvent(gamepad, new GamepadState {
            leftTrigger = 0.2345f
        }, 3 + 0.002);
        InputSystem.QueueStateEvent(gamepad, new GamepadState {
            leftTrigger = 0.3456f
        }, 3 + 1.0 / 60 + 0.001);
        InputSystem.QueueStateEvent(gamepad, new GamepadState {
            leftTrigger = 0.4567f
        }, 3 + 2 * (1.0 / 60) + 0.001);

        InputSystem.Update(InputUpdateType.Fixed);

        Assert.That(receivedEvents, Has.Count.EqualTo(2));
        Assert.That(receivedEvents[0].time, Is.EqualTo(3 + 0.001).Within(0.00001));
        Assert.That(receivedEvents[1].time, Is.EqualTo(3 + 0.002).Within(0.00001));
        Assert.That(gamepad.leftTrigger.ReadValue(), Is.EqualTo(0.2345).Within(0.00001));

        Assert.That(InputUpdate.s_LastUpdateRetainedEventCount, Is.EqualTo(2));
        Assert.That(InputUpdate.s_LastFixedUpdateTime, Is.EqualTo(3 + 1.0 / 60).Within(0.0001));

        receivedEvents.Clear();

        InputSystem.Update(InputUpdateType.Fixed);

        Assert.That(receivedEvents, Has.Count.EqualTo(1));
        Assert.That(receivedEvents[0].time, Is.EqualTo(3 + 1.0 / 60 + 0.001).Within(0.00001));
        Assert.That(gamepad.leftTrigger.ReadValue(), Is.EqualTo(0.3456).Within(0.00001));

        Assert.That(InputUpdate.s_LastUpdateRetainedEventCount, Is.EqualTo(1));
        Assert.That(InputUpdate.s_LastFixedUpdateTime, Is.EqualTo(3 + 2 * (1.0 / 60)).Within(0.0001));

        receivedEvents.Clear();

        InputSystem.Update(InputUpdateType.Fixed);

        Assert.That(receivedEvents, Has.Count.EqualTo(1));
        Assert.That(receivedEvents[0].time, Is.EqualTo(3 + 2 * (1.0 / 60) + 0.001).Within(0.00001));
        Assert.That(gamepad.leftTrigger.ReadValue(), Is.EqualTo(0.4567).Within(0.00001));

        Assert.That(InputUpdate.s_LastUpdateRetainedEventCount, Is.Zero);
        Assert.That(InputUpdate.s_LastFixedUpdateTime, Is.EqualTo(3 + 3 * (1.0 / 60)).Within(0.0001));

        receivedEvents.Clear();

        InputSystem.Update(InputUpdateType.Fixed);

        Assert.That(receivedEvents, Has.Count.Zero);
        Assert.That(gamepad.leftTrigger.ReadValue(), Is.EqualTo(0.4567).Within(0.00001));

        Assert.That(InputUpdate.s_LastUpdateRetainedEventCount, Is.Zero);
        Assert.That(InputUpdate.s_LastFixedUpdateTime, Is.EqualTo(3 + 4 * (1.0 / 60)).Within(0.0001));
    }
    public unsafe void Events_AreTimeslicedByDefault()
    {
        InputSystem.settings.updateMode = InputSettings.UpdateMode.ProcessEventsInFixedUpdate;

        runtime.currentTimeForFixedUpdate = 1;

        var gamepad = InputSystem.AddDevice <Gamepad>();

        var receivedEvents = new List <InputEvent>();

        InputSystem.onEvent +=
            (eventPtr, _) => receivedEvents.Add(*eventPtr.data);

        // First fixed update should just take everything.
        InputSystem.QueueStateEvent(gamepad, new GamepadState {
            leftTrigger = 0.1234f
        }, 1);
        InputSystem.QueueStateEvent(gamepad, new GamepadState {
            leftTrigger = 0.2345f
        }, 2);
        InputSystem.QueueStateEvent(gamepad, new GamepadState {
            leftTrigger = 0.3456f
        }, 2.9);

        runtime.currentTimeForFixedUpdate = 3;

        InputSystem.Update(InputUpdateType.Fixed);

        Assert.That(receivedEvents, Has.Count.EqualTo(3));
        Assert.That(receivedEvents[0].time, Is.EqualTo(1).Within(0.00001));
        Assert.That(receivedEvents[1].time, Is.EqualTo(2).Within(0.00001));
        Assert.That(receivedEvents[2].time, Is.EqualTo(2.9).Within(0.00001));
        Assert.That(gamepad.leftTrigger.ReadValue(), Is.EqualTo(0.3456).Within(0.00001));

        Assert.That(InputUpdate.s_LastUpdateRetainedEventCount, Is.Zero);

        receivedEvents.Clear();

        runtime.currentTimeForFixedUpdate += 1 / 60.0f;

        // From now on, fixed updates should only take what falls in their slice.
        InputSystem.QueueStateEvent(gamepad, new GamepadState {
            leftTrigger = 0.1234f
        }, 3 + 0.001);
        InputSystem.QueueStateEvent(gamepad, new GamepadState {
            leftTrigger = 0.2345f
        }, 3 + 0.002);
        InputSystem.QueueStateEvent(gamepad, new GamepadState {
            leftTrigger = 0.3456f
        }, 3 + 1.0 / 60 + 0.001);
        InputSystem.QueueStateEvent(gamepad, new GamepadState {
            leftTrigger = 0.4567f
        }, 3 + 2 * (1.0 / 60) + 0.001);

        InputSystem.Update(InputUpdateType.Fixed);

        Assert.That(receivedEvents, Has.Count.EqualTo(2));
        Assert.That(receivedEvents[0].time, Is.EqualTo(3 + 0.001).Within(0.00001));
        Assert.That(receivedEvents[1].time, Is.EqualTo(3 + 0.002).Within(0.00001));
        Assert.That(gamepad.leftTrigger.ReadValue(), Is.EqualTo(0.2345).Within(0.00001));

        Assert.That(InputUpdate.s_LastUpdateRetainedEventCount, Is.EqualTo(2));

        receivedEvents.Clear();

        runtime.currentTimeForFixedUpdate += 1 / 60.0f;

        InputSystem.Update(InputUpdateType.Fixed);

        Assert.That(receivedEvents, Has.Count.EqualTo(1));
        Assert.That(receivedEvents[0].time, Is.EqualTo(3 + 1.0 / 60 + 0.001).Within(0.00001));
        Assert.That(gamepad.leftTrigger.ReadValue(), Is.EqualTo(0.3456).Within(0.00001));

        Assert.That(InputUpdate.s_LastUpdateRetainedEventCount, Is.EqualTo(1));

        receivedEvents.Clear();

        runtime.currentTimeForFixedUpdate += 1 / 60.0f;

        InputSystem.Update(InputUpdateType.Fixed);

        Assert.That(receivedEvents, Has.Count.EqualTo(1));
        Assert.That(receivedEvents[0].time, Is.EqualTo(3 + 2 * (1.0 / 60) + 0.001).Within(0.00001));
        Assert.That(gamepad.leftTrigger.ReadValue(), Is.EqualTo(0.4567).Within(0.00001));

        Assert.That(InputUpdate.s_LastUpdateRetainedEventCount, Is.Zero);

        receivedEvents.Clear();

        runtime.currentTimeForFixedUpdate += 1 / 60.0f;

        InputSystem.Update(InputUpdateType.Fixed);

        Assert.That(receivedEvents, Has.Count.Zero);
        Assert.That(gamepad.leftTrigger.ReadValue(), Is.EqualTo(0.4567).Within(0.00001));

        Assert.That(InputUpdate.s_LastUpdateRetainedEventCount, Is.Zero);
    }
    public void Controls_CanKeepListsOfControls_WithoutAllocatingGCMemory()
    {
        InputSystem.AddDevice <Mouse>(); // Noise.
        var gamepad  = InputSystem.AddDevice <Gamepad>();
        var keyboard = InputSystem.AddDevice <Keyboard>();

        var list = new InputControlList <InputControl>();

        try
        {
            Assert.That(list.Count, Is.Zero);
            Assert.That(list.ToArray(), Is.Empty);
            Assert.That(() => list[0], Throws.TypeOf <ArgumentOutOfRangeException>());

            list.Capacity = 10;

            list.Add(gamepad.leftStick);
            list.Add(null); // Permissible to add null entry.
            list.Add(keyboard.spaceKey);
            list.Add(keyboard);

            Assert.That(list.Count, Is.EqualTo(4));
            Assert.That(list.Capacity, Is.EqualTo(6));
            Assert.That(list[0], Is.SameAs(gamepad.leftStick));
            Assert.That(list[1], Is.Null);
            Assert.That(list[2], Is.SameAs(keyboard.spaceKey));
            Assert.That(list[3], Is.SameAs(keyboard));
            Assert.That(() => list[4], Throws.TypeOf <ArgumentOutOfRangeException>());
            Assert.That(list.ToArray(),
                        Is.EquivalentTo(new InputControl[] { gamepad.leftStick, null, keyboard.spaceKey, keyboard }));
            Assert.That(list.Contains(gamepad.leftStick));
            Assert.That(list.Contains(null));
            Assert.That(list.Contains(keyboard.spaceKey));
            Assert.That(list.Contains(keyboard));

            list.RemoveAt(1);
            list.Remove(keyboard);

            Assert.That(list.Count, Is.EqualTo(2));
            Assert.That(list.Capacity, Is.EqualTo(8));
            Assert.That(list[0], Is.SameAs(gamepad.leftStick));
            Assert.That(list[1], Is.SameAs(keyboard.spaceKey));
            Assert.That(() => list[2], Throws.TypeOf <ArgumentOutOfRangeException>());
            Assert.That(list.ToArray(), Is.EquivalentTo(new InputControl[] { gamepad.leftStick, keyboard.spaceKey }));
            Assert.That(list.Contains(gamepad.leftStick));
            Assert.That(!list.Contains(null));
            Assert.That(list.Contains(keyboard.spaceKey));
            Assert.That(!list.Contains(keyboard));

            list.AddRange(new InputControl[] { keyboard.aKey, keyboard.bKey }, count: 1, destinationIndex: 0);

            Assert.That(list.Count, Is.EqualTo(3));
            Assert.That(list.Capacity, Is.EqualTo(7));
            Assert.That(list,
                        Is.EquivalentTo(new InputControl[]
                                        { keyboard.aKey, gamepad.leftStick, keyboard.spaceKey }));

            list.AddRange(new InputControl[] { keyboard.bKey, keyboard.cKey });

            Assert.That(list.Count, Is.EqualTo(5));
            Assert.That(list.Capacity, Is.EqualTo(5));
            Assert.That(list,
                        Is.EquivalentTo(new InputControl[]
                                        { keyboard.aKey, gamepad.leftStick, keyboard.spaceKey, keyboard.bKey, keyboard.cKey }));

            using (var toAdd = new InputControl[] { gamepad.buttonNorth, gamepad.buttonEast, gamepad.buttonWest }.ToControlList())
                list.AddSlice(toAdd, count: 1, destinationIndex: 1, sourceIndex: 2);

            Assert.That(list.Count, Is.EqualTo(6));
            Assert.That(list.Capacity, Is.EqualTo(4));
            Assert.That(list,
                        Is.EquivalentTo(new InputControl[]
                                        { keyboard.aKey, gamepad.buttonWest, gamepad.leftStick, keyboard.spaceKey, keyboard.bKey, keyboard.cKey }));

            list[0] = keyboard.zKey;

            Assert.That(list,
                        Is.EquivalentTo(new InputControl[]
                                        { keyboard.zKey, gamepad.buttonWest, gamepad.leftStick, keyboard.spaceKey, keyboard.bKey, keyboard.cKey }));

            list.Clear();

            Assert.That(list.Count, Is.Zero);
            Assert.That(list.Capacity, Is.EqualTo(10));
            Assert.That(list.ToArray(), Is.Empty);
            Assert.That(() => list[0], Throws.TypeOf <ArgumentOutOfRangeException>());
            Assert.That(!list.Contains(gamepad.leftStick));
            Assert.That(!list.Contains(null));
            Assert.That(!list.Contains(keyboard.spaceKey));
            Assert.That(!list.Contains(keyboard));
        }
        finally
        {
            list.Dispose();
        }
    }