예제 #1
0
        public FakeRemote()
        {
            runtime = new InputTestRuntime();
            var manager = new InputManager();

            manager.m_Settings = ScriptableObject.CreateInstance <InputSettings>();
            manager.InitializeData();
            manager.InstallRuntime(runtime);
            manager.ApplySettings();

            local  = new InputRemoting(InputSystem.s_Manager);
            remote = new InputRemoting(manager);

            var remoteInstaller = new GlobalsInstallerObserver(manager);
            var localInstaller  = new GlobalsInstallerObserver(InputSystem.s_Manager);

            // The installers will ensure the globals environment is prepared right before
            // the receiver processes the message. There are some static fields, such as
            // the layouts collection, that needs to be set to that InputManager's version.
            // After processing, the environment will be reverted back to the local manager
            // to keep it the default.
            local.Subscribe(remoteInstaller);
            local.Subscribe(remote);
            local.Subscribe(localInstaller);
            remote.Subscribe(localInstaller);
            remote.Subscribe(local);

            local.StartSending();
        }
예제 #2
0
    public void Remote_CanConnectTwoInputSystemsOverNetwork()
    {
        // Add some data to the local input system.
        InputSystem.AddDevice("Gamepad");
        InputSystem.RegisterControlLayout(@"{ ""name"" : ""MyGamepad"", ""extend"" : ""Gamepad"" }");
        var localGamepad = (Gamepad)InputSystem.AddDevice("MyGamepad");

        // Now create another input system instance and connect it
        // to our "local" instance.
        // NOTE: This relies on internal APIs. We want remoting as such to be available
        //       entirely from user land but having multiple input systems in the same
        //       application isn't something that we necessarily want to expose (we do
        //       have global state so it can easily lead to surprising results).
        var secondInputRuntime = new InputTestRuntime();
        var secondInputManager = new InputManager();

        secondInputManager.InstallRuntime(secondInputRuntime);
        secondInputManager.InitializeData();

        var local  = new InputRemoting(InputSystem.s_Manager);
        var remote = new InputRemoting(secondInputManager);

        // We wire the two directly into each other effectively making function calls
        // our "network transport layer". In a real networking situation, we'd effectively
        // have an RPC-like mechanism sitting in-between.
        local.Subscribe(remote);
        remote.Subscribe(local);

        local.StartSending();

        var remoteGamepadLayout =
            string.Format("{0}0::{1}", InputRemoting.kRemoteLayoutNamespacePrefix, localGamepad.layout);

        // Make sure that our "remote" system now has the data we initially
        // set up on the local system.
        Assert.That(secondInputManager.devices,
                    Has.Exactly(1).With.Property("layout").EqualTo(remoteGamepadLayout));
        Assert.That(secondInputManager.devices, Has.Exactly(2).TypeOf <Gamepad>());
        Assert.That(secondInputManager.devices, Has.All.With.Property("remote").True);

        // Send state event to local gamepad.
        InputSystem.QueueStateEvent(localGamepad, new GamepadState {
            leftTrigger = 0.5f
        });
        InputSystem.Update();

        // Make second input manager process the events it got.
        // NOTE: This will also switch the system to the state buffers from the second input manager.
        secondInputManager.Update();

        var remoteGamepad = (Gamepad)secondInputManager.devices.First(x => x.layout == remoteGamepadLayout);

        Assert.That(remoteGamepad.leftTrigger.ReadValue(), Is.EqualTo(0.5).Within(0.0000001));

        secondInputRuntime.Dispose();
    }
예제 #3
0
        public void Receiver()
        {
            var receiver         = new Receiver(_channel1);
            var receiverInput    = new InputRemoting(receiver);
            var receiverDisposer = receiverInput.Subscribe(receiverInput);

            receiverInput.StartSending();
            receiverInput.StopSending();
            receiverDisposer.Dispose();
        }
예제 #4
0
        public void Sender()
        {
            var sender         = new Sender();
            var senderInput    = new InputRemoting(sender);
            var senderDisposer = senderInput.Subscribe(new Observer(_channel1));

            senderInput.StartSending();
            senderInput.StopSending();
            senderDisposer.Dispose();
        }
        public void Receiver()
        {
            var receiver = new Receiver(_channel1);

            Assert.That(receiver.remoteDevices, Is.Empty);
            Assert.That(receiver.remoteLayouts, Is.Empty);
            var receiverInput    = new InputRemoting(receiver);
            var receiverDisposer = receiverInput.Subscribe(receiverInput);

            receiverInput.StartSending();
            receiverInput.StopSending();
            receiverDisposer.Dispose();
        }
    public void Remote_CanConnectInputSystemsOverEditorPlayerConnection()
    {
        var connectionToEditor = ScriptableObject.CreateInstance <RemoteInputPlayerConnection>();
        var connectionToPlayer = ScriptableObject.CreateInstance <RemoteInputPlayerConnection>();

        connectionToEditor.name = "ConnectionToEditor";
        connectionToPlayer.name = "ConnectionToPlayer";

        var fakeEditorConnection = new FakePlayerConnection {
            playerId = 0
        };
        var fakePlayerConnection = new FakePlayerConnection {
            playerId = 1
        };

        fakeEditorConnection.otherEnd = fakePlayerConnection;
        fakePlayerConnection.otherEnd = fakeEditorConnection;

        var observer = new RemoteTestObserver();

        // In the Unity API, "PlayerConnection" is the connection to the editor
        // and "EditorConnection" is the connection to the player. Seems counter-intuitive.
        connectionToEditor.Bind(fakePlayerConnection, true);
        connectionToPlayer.Bind(fakeEditorConnection, true);

        // Bind a local remote on the player side.
        var local = new InputRemoting(InputSystem.s_Manager);

        local.Subscribe(connectionToEditor);
        local.StartSending();

        connectionToPlayer.Subscribe(observer);

        var device = InputSystem.AddDevice("Gamepad");

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

        ////TODO: make sure that we also get the connection sequence right and send our initial layouts and devices
        Assert.That(observer.messages, Has.Count.EqualTo(4));
        Assert.That(observer.messages[0].type, Is.EqualTo(InputRemoting.MessageType.Connect));
        Assert.That(observer.messages[1].type, Is.EqualTo(InputRemoting.MessageType.NewDevice));
        Assert.That(observer.messages[2].type, Is.EqualTo(InputRemoting.MessageType.NewEvents));
        Assert.That(observer.messages[3].type, Is.EqualTo(InputRemoting.MessageType.RemoveDevice));

        ////TODO: test disconnection

        ScriptableObject.Destroy(connectionToEditor);
        ScriptableObject.Destroy(connectionToPlayer);
    }
        public void Sender()
        {
            var sender = new Sender();

            Assert.That(sender.layouts, Is.Not.Empty);
            Assert.That(sender.devices, Is.Not.Empty);
            var senderInput    = new InputRemoting(sender);
            var senderDisposer = senderInput.Subscribe(new Observer(_channel1));

            senderInput.StartSending();
            senderInput.StopSending();
            senderDisposer.Dispose();
            sender.Dispose();
        }
        public IEnumerator AddDevice()
        {
            var sender      = new Sender();
            var senderInput = new InputRemoting(sender);
            var senderSubscriberDisposer = senderInput.Subscribe(new Observer(_channel1));

            var receiver      = new Receiver(_channel2);
            var receiverInput = new InputRemoting(receiver);
            var receiverSubscriberDisposer = receiverInput.Subscribe(receiverInput);

            InputDevice       device = null;
            InputDeviceChange change = default;

            receiver.onDeviceChange += (_device, _change) => {
                device = _device;
                change = _change;
            };
            string layoutName = null;
            InputControlLayoutChange layoutChange = default;

            receiver.onLayoutChange += (_name, _change) => {
                layoutName   = _name;
                layoutChange = _change;
            };

            receiverInput.StartSending();
            senderInput.StartSending();

            yield return(new WaitUntil(() => device != null));

            yield return(new WaitUntil(() => layoutName != null));

            Assert.That(device, Is.Not.Null);
            Assert.That(change, Is.EqualTo(InputDeviceChange.Added));
            Assert.That(layoutName, Is.Not.Null);
            Assert.That(layoutChange, Is.EqualTo(InputControlLayoutChange.Added));

            Assert.That(receiver.remoteLayouts, Is.Not.Empty);
            Assert.That(receiver.remoteDevices, Is.Not.Empty);
            Assert.That(receiver.remoteDevices, Has.All.Matches <InputDevice>(d => d.remote));

            senderInput.StopSending();
            receiverInput.StopSending();

            senderSubscriberDisposer.Dispose();
            receiverSubscriberDisposer.Dispose();
            sender.Dispose();
            receiver.Dispose();
        }
        public FakeRemote()
        {
            runtime = new InputTestRuntime();
            manager = new InputManager();
            manager.InstallRuntime(runtime);
            manager.InitializeData();

            local  = new InputRemoting(InputSystem.s_Manager);
            remote = new InputRemoting(manager);

            local.Subscribe(remote);
            remote.Subscribe(local);

            local.StartSending();
        }
예제 #10
0
    public void Remote_ChangingLayoutsWhileRemoting_WillSendChangesToRemote()
    {
        var secondInputSystem = new InputManager();

        secondInputSystem.InitializeData();

        var local  = new InputRemoting(InputSystem.s_Manager);
        var remote = new InputRemoting(secondInputSystem);

        local.Subscribe(remote);
        remote.Subscribe(local);

        local.StartSending();

        const string jsonV1 = @"
            {
                ""name"" : ""MyLayout"",
                ""extend"" : ""Gamepad""
            }
        ";

        // Add layout.
        InputSystem.RegisterControlLayout(jsonV1);

        var layout = secondInputSystem.TryLoadControlLayout(new InternedString("remote0::MyLayout"));

        Assert.That(layout, Is.Not.Null);
        Assert.That(layout.extendsLayout, Is.EqualTo("remote0::Gamepad"));

        const string jsonV2 = @"
            {
                ""name"" : ""MyLayout"",
                ""extend"" : ""Keyboard""
            }
        ";

        // Change layout.
        InputSystem.RegisterControlLayout(jsonV2);

        layout = secondInputSystem.TryLoadControlLayout(new InternedString("remote0::MyLayout"));
        Assert.That(layout.extendsLayout, Is.EqualTo("remote0::Keyboard"));

        // Remove layout.
        InputSystem.RemoveControlLayout("MyLayout");

        Assert.That(secondInputSystem.TryLoadControlLayout(new InternedString("remote0::MyLayout")), Is.Null);
    }
예제 #11
0
        public FakeRemote()
        {
            runtime            = new InputTestRuntime();
            manager            = new InputManager();
            manager.m_Settings = ScriptableObject.CreateInstance <InputSettings>();
            manager.InstallRuntime(runtime);
            manager.InitializeData();
            manager.ApplySettings();

            local  = new InputRemoting(InputSystem.s_Manager);
            remote = new InputRemoting(manager);

            local.Subscribe(remote);
            remote.Subscribe(local);

            local.StartSending();
        }
예제 #12
0
    public void Remote_ChangingDevicesWhileRemoting_WillSendChangesToRemote()
    {
        var secondInputRuntime = new InputTestRuntime();
        var secondInputManager = new InputManager();

        secondInputManager.InstallRuntime(secondInputRuntime);
        secondInputManager.InitializeData();

        var local  = new InputRemoting(InputSystem.s_Manager);
        var remote = new InputRemoting(secondInputManager);

        local.Subscribe(remote);
        remote.Subscribe(local);

        local.StartSending();

        // Add device.
        var localGamepad = InputSystem.AddDevice("Gamepad");

        secondInputManager.Update();

        Assert.That(secondInputManager.devices, Has.Count.EqualTo(1));
        var remoteGamepad = secondInputManager.devices[0];

        Assert.That(remoteGamepad, Is.TypeOf <Gamepad>());
        Assert.That(remoteGamepad.remote, Is.True);
        Assert.That(remoteGamepad.layout, Contains.Substring("Gamepad"));

        // Change usage.
        InputSystem.SetUsage(localGamepad, CommonUsages.LeftHand);
        secondInputManager.Update();
        Assert.That(remoteGamepad.usages, Has.Exactly(1).EqualTo(CommonUsages.LeftHand));

        // Bind and disconnect are events so no need to test those.

        // Remove device.
        InputSystem.RemoveDevice(localGamepad);
        secondInputManager.Update();
        Assert.That(secondInputManager.devices, Has.Count.Zero);

        secondInputRuntime.Dispose();
    }
예제 #13
0
    public void Remote_CanConnectInputSystemsOverEditorPlayerConnection()
    {
#if UNITY_EDITOR
        // In the editor, RemoteInputPlayerConnection is a scriptable singleton. Creating multiple instances of it
        // will cause an error messages - but will work nevertheless, so we expect those errors to let us run the test.
        // We call RemoteInputPlayerConnection.instance once to make sure that we an instance is created, and we get
        // a deterministic number of two errors.
        var instance = RemoteInputPlayerConnection.instance;
        UnityEngine.TestTools.LogAssert.Expect(LogType.Error, "ScriptableSingleton already exists. Did you query the singleton in a constructor?");
        UnityEngine.TestTools.LogAssert.Expect(LogType.Error, "ScriptableSingleton already exists. Did you query the singleton in a constructor?");
#endif
        var connectionToEditor = ScriptableObject.CreateInstance <RemoteInputPlayerConnection>();
        var connectionToPlayer = ScriptableObject.CreateInstance <RemoteInputPlayerConnection>();

        connectionToEditor.name = "ConnectionToEditor";
        connectionToPlayer.name = "ConnectionToPlayer";

        var fakeEditorConnection = new FakePlayerConnection {
            playerId = 0
        };
        var fakePlayerConnection = new FakePlayerConnection {
            playerId = 1
        };

        fakeEditorConnection.otherEnd = fakePlayerConnection;
        fakePlayerConnection.otherEnd = fakeEditorConnection;

        var observerEditor = new RemoteTestObserver();
        var observerPlayer = new RemoteTestObserver();

        // In the Unity API, "PlayerConnection" is the connection to the editor
        // and "EditorConnection" is the connection to the player. Seems counter-intuitive.
        connectionToEditor.Bind(fakePlayerConnection, true);
        connectionToPlayer.Bind(fakeEditorConnection, true);

        // Bind a local remote on the player side.
        var local = new InputRemoting(InputSystem.s_Manager);
        local.Subscribe(connectionToEditor);

        connectionToEditor.Subscribe(local);
        connectionToPlayer.Subscribe(observerEditor);
        connectionToEditor.Subscribe(observerPlayer);

        fakeEditorConnection.Send(RemoteInputPlayerConnection.kStartSendingMsg, null);

        var device = InputSystem.AddDevice <Gamepad>();
        InputSystem.QueueStateEvent(device, new GamepadState());
        InputSystem.Update();
        InputSystem.RemoveDevice(device);

        fakeEditorConnection.Send(RemoteInputPlayerConnection.kStopSendingMsg, null);

        // We should not obseve any messages for these, as we stopped sending!
        device = InputSystem.AddDevice <Gamepad>();
        InputSystem.QueueStateEvent(device, new GamepadState());
        InputSystem.Update();
        InputSystem.RemoveDevice(device);

        fakeEditorConnection.DisconnectAll();

        ////TODO: make sure that we also get the connection sequence right and send our initial layouts and devices
        Assert.That(observerEditor.messages, Has.Count.EqualTo(5));
        Assert.That(observerEditor.messages[0].type, Is.EqualTo(InputRemoting.MessageType.Connect));
        Assert.That(observerEditor.messages[1].type, Is.EqualTo(InputRemoting.MessageType.NewDevice));
        Assert.That(observerEditor.messages[2].type, Is.EqualTo(InputRemoting.MessageType.NewEvents));
        Assert.That(observerEditor.messages[3].type, Is.EqualTo(InputRemoting.MessageType.RemoveDevice));
        Assert.That(observerEditor.messages[4].type, Is.EqualTo(InputRemoting.MessageType.Disconnect));

        Assert.That(observerPlayer.messages, Has.Count.EqualTo(3));
        Assert.That(observerPlayer.messages[0].type, Is.EqualTo(InputRemoting.MessageType.Connect));
        Assert.That(observerPlayer.messages[1].type, Is.EqualTo(InputRemoting.MessageType.StartSending));
        Assert.That(observerPlayer.messages[2].type, Is.EqualTo(InputRemoting.MessageType.StopSending));

        Object.Destroy(connectionToEditor);
        Object.Destroy(connectionToPlayer);
    }