NEW: Can run tests in player.
This commit is contained in:
Родитель
bbe1252fba
Коммит
c9b310ff95
|
@ -17,7 +17,7 @@ namespace ISX.HID
|
|||
// The HID device descriptor as received from the device driver.
|
||||
public HIDDeviceDescriptor hidDescriptor => new HIDDeviceDescriptor();////TODO: parse on demand from description.capabilities
|
||||
|
||||
internal static string OnDeviceDiscovered(InputDeviceDescription description, string matchedTemplate)
|
||||
internal static string OnFindTemplateForDevice(InputDeviceDescription description, string matchedTemplate)
|
||||
{
|
||||
// If the system found a matching template, there's nothing for us to do.
|
||||
if (!string.IsNullOrEmpty(matchedTemplate))
|
||||
|
@ -40,10 +40,11 @@ namespace ISX.HID
|
|||
HIDDeviceDescriptor hidDeviceDescriptor;
|
||||
try
|
||||
{
|
||||
hidDeviceDescriptor = JsonUtility.FromJson<HIDDeviceDescriptor>(description.capabilities);
|
||||
hidDeviceDescriptor = HIDDeviceDescriptor.FromJson(description.capabilities);
|
||||
}
|
||||
catch (Exception ex)
|
||||
catch (Exception exception)
|
||||
{
|
||||
Debug.Log($"Could not parse HID descriptor (exception: {exception}");
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -66,6 +67,7 @@ namespace ISX.HID
|
|||
var baseTemplate = "HID";
|
||||
if (hidDeviceDescriptor.usagePage == UsagePage.GenericDesktop)
|
||||
{
|
||||
////TODO: there's some work to be done to make the HID *actually* compatible with these devices
|
||||
if (hidDeviceDescriptor.usage == (int)GenericDesktop.Joystick)
|
||||
baseTemplate = "Joystick";
|
||||
else if (hidDeviceDescriptor.usage == (int)GenericDesktop.Gamepad)
|
||||
|
@ -98,7 +100,8 @@ namespace ISX.HID
|
|||
{
|
||||
var builder = new InputTemplate.Builder
|
||||
{
|
||||
type = typeof(HID)
|
||||
type = typeof(HID),
|
||||
stateFormat = new FourCC('H', 'I', 'D')
|
||||
};
|
||||
|
||||
////TODO: for joysticks, set up stick from X and Y
|
||||
|
@ -113,9 +116,11 @@ namespace ISX.HID
|
|||
var control =
|
||||
builder.AddControl(element.DetermineName())
|
||||
.WithTemplate(template)
|
||||
.WithOffset(offset)
|
||||
.WithOffset(offset) ////FIXME: offset is in bits; handle bit addressing correctly
|
||||
.WithFormat(element.DetermineFormat());
|
||||
|
||||
////TODO: configure axis parameters from min/max limits
|
||||
|
||||
element.SetUsage(control);
|
||||
}
|
||||
|
||||
|
@ -183,6 +188,8 @@ namespace ISX.HID
|
|||
if (reportType != HIDReportType.Input)
|
||||
return null;
|
||||
|
||||
////TODO: deal with arrays
|
||||
|
||||
switch (usagePage)
|
||||
{
|
||||
case UsagePage.Button:
|
||||
|
@ -234,6 +241,16 @@ namespace ISX.HID
|
|||
public int usage;
|
||||
public UsagePage usagePage;
|
||||
public HIDElementDescriptor[] elements;
|
||||
|
||||
public string ToJson()
|
||||
{
|
||||
return JsonUtility.ToJson(this);
|
||||
}
|
||||
|
||||
public static HIDDeviceDescriptor FromJson(string json)
|
||||
{
|
||||
return JsonUtility.FromJson<HIDDeviceDescriptor>(json);
|
||||
}
|
||||
}
|
||||
|
||||
public enum UsagePage
|
||||
|
|
|
@ -2,7 +2,7 @@ using UnityEngine;
|
|||
|
||||
namespace ISX.HID
|
||||
{
|
||||
[InputPlugin]
|
||||
[InputModule]
|
||||
public static class HIDSupport
|
||||
{
|
||||
public static string description =>
|
||||
|
@ -22,7 +22,7 @@ namespace ISX.HID
|
|||
public static void Initialize()
|
||||
{
|
||||
InputSystem.RegisterTemplate<HID>();
|
||||
InputSystem.onDeviceDiscovered += HID.OnDeviceDiscovered;
|
||||
InputSystem.onFindTemplateForDevice += HID.OnFindTemplateForDevice;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
using NUnit.Framework;
|
||||
using UnityEngine;
|
||||
|
||||
namespace ISX.HID
|
||||
{
|
||||
|
@ -9,7 +8,6 @@ namespace ISX.HID
|
|||
{
|
||||
base.Setup();
|
||||
|
||||
////TODO: the system should do that automatically for us
|
||||
HIDSupport.Initialize();
|
||||
}
|
||||
|
||||
|
@ -38,7 +36,7 @@ namespace ISX.HID
|
|||
{
|
||||
interfaceName = HID.kHIDInterface,
|
||||
product = "MyHIDThing",
|
||||
capabilities = JsonUtility.ToJson(hidDescriptor)
|
||||
capabilities = hidDescriptor.ToJson()
|
||||
});
|
||||
|
||||
Assert.That(InputSystem.devices, Has.Count.EqualTo(1));
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
#if DEVELOPMENT_BUILD || UNITY_EDITOR
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using ISX;
|
||||
using ISX.Remote;
|
||||
using NUnit.Framework;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
using UnityEngine.Networking.PlayerConnection;
|
||||
using UnityEngine.TestTools;
|
||||
using UnityEngineInternal.Input;
|
||||
|
||||
|
@ -261,7 +265,7 @@ public class FunctionalTests : InputTestsBase
|
|||
[Category("Template")]
|
||||
public void Templates_CanOverrideTemplateMatchesForDiscoveredDevices()
|
||||
{
|
||||
InputSystem.onDeviceDiscovered +=
|
||||
InputSystem.onFindTemplateForDevice +=
|
||||
(description, templateMatch) => "Keyboard";
|
||||
|
||||
var device = InputSystem.AddDevice(new InputDeviceDescription {deviceClass = "Gamepad"});
|
||||
|
@ -3510,9 +3514,9 @@ public class FunctionalTests : InputTestsBase
|
|||
modifiers: "tap(duration=0.1),slowTap(duration=0.5)");
|
||||
action.Enable();
|
||||
|
||||
var started = new System.Collections.Generic.List<InputAction.CallbackContext>();
|
||||
var performed = new System.Collections.Generic.List<InputAction.CallbackContext>();
|
||||
var cancelled = new System.Collections.Generic.List<InputAction.CallbackContext>();
|
||||
var started = new List<InputAction.CallbackContext>();
|
||||
var performed = new List<InputAction.CallbackContext>();
|
||||
var cancelled = new List<InputAction.CallbackContext>();
|
||||
|
||||
action.started += ctx => started.Add(ctx);
|
||||
action.performed += ctx => performed.Add(ctx);
|
||||
|
@ -3569,7 +3573,7 @@ public class FunctionalTests : InputTestsBase
|
|||
action.AddBinding("/gamepad/leftTrigger").CombinedWith("/gamepad/buttonSouth");
|
||||
action.Enable();
|
||||
|
||||
var performed = new System.Collections.Generic.List<InputAction.CallbackContext>();
|
||||
var performed = new List<InputAction.CallbackContext>();
|
||||
action.performed += ctx => performed.Add(ctx);
|
||||
|
||||
InputSystem.QueueStateEvent(gamepad, new GamepadState {leftTrigger = 1.0f});
|
||||
|
@ -3596,7 +3600,7 @@ public class FunctionalTests : InputTestsBase
|
|||
action.AddBinding("/gamepad/leftTrigger").CombinedWith("/gamepad/buttonSouth");
|
||||
action.Enable();
|
||||
|
||||
var performed = new System.Collections.Generic.List<InputAction.CallbackContext>();
|
||||
var performed = new List<InputAction.CallbackContext>();
|
||||
action.performed += ctx => performed.Add(ctx);
|
||||
|
||||
InputSystem.QueueStateEvent(gamepad,
|
||||
|
@ -3616,7 +3620,7 @@ public class FunctionalTests : InputTestsBase
|
|||
action.AddBinding("/gamepad/leftTrigger").CombinedWith("/gamepad/buttonSouth");
|
||||
action.Enable();
|
||||
|
||||
var performed = new System.Collections.Generic.List<InputAction.CallbackContext>();
|
||||
var performed = new List<InputAction.CallbackContext>();
|
||||
action.performed += ctx => performed.Add(ctx);
|
||||
|
||||
InputSystem.QueueStateEvent(gamepad,
|
||||
|
@ -3643,7 +3647,7 @@ public class FunctionalTests : InputTestsBase
|
|||
action.AddBinding("/gamepad/leftTrigger").CombinedWith("/gamepad/buttonSouth", modifiers: "tap,slowTap");
|
||||
action.Enable();
|
||||
|
||||
var performed = new System.Collections.Generic.List<InputAction.CallbackContext>();
|
||||
var performed = new List<InputAction.CallbackContext>();
|
||||
action.performed += ctx => performed.Add(ctx);
|
||||
|
||||
InputSystem.QueueStateEvent(gamepad,
|
||||
|
@ -3665,9 +3669,9 @@ public class FunctionalTests : InputTestsBase
|
|||
var action = new InputAction(binding: "/gamepad/leftStick", modifiers: "continuous");
|
||||
action.Enable();
|
||||
|
||||
var started = new System.Collections.Generic.List<InputAction.CallbackContext>();
|
||||
var performed = new System.Collections.Generic.List<InputAction.CallbackContext>();
|
||||
var cancelled = new System.Collections.Generic.List<InputAction.CallbackContext>();
|
||||
var started = new List<InputAction.CallbackContext>();
|
||||
var performed = new List<InputAction.CallbackContext>();
|
||||
var cancelled = new List<InputAction.CallbackContext>();
|
||||
|
||||
action.started += ctx => performed.Add(ctx);
|
||||
action.cancelled += ctx => performed.Add(ctx);
|
||||
|
@ -4256,7 +4260,7 @@ public class FunctionalTests : InputTestsBase
|
|||
var secondInputSystem = new InputManager();
|
||||
secondInputSystem.InitializeData();
|
||||
|
||||
var local = InputSystem.remote;
|
||||
var local = InputSystem.remoting;
|
||||
var remote = new InputRemoting(secondInputSystem, senderId: 1);
|
||||
|
||||
// We wire the two directly into each other effectively making function calls
|
||||
|
@ -4297,7 +4301,7 @@ public class FunctionalTests : InputTestsBase
|
|||
var secondInputSystem = new InputManager();
|
||||
secondInputSystem.InitializeData();
|
||||
|
||||
var local = InputSystem.remote;
|
||||
var local = InputSystem.remoting;
|
||||
var remote = new InputRemoting(secondInputSystem, senderId: 1);
|
||||
|
||||
local.Subscribe(remote);
|
||||
|
@ -4332,6 +4336,142 @@ public class FunctionalTests : InputTestsBase
|
|||
Assert.Fail();
|
||||
}
|
||||
|
||||
// If we have more than two players connected, for example, and we add a template from player A
|
||||
// to the system, we don't want to send the template to player B in turn. I.e. all data mirrored
|
||||
// from remotes should stay local.
|
||||
[Test]
|
||||
[Category("Remote")]
|
||||
public void TODO_Remote_WithMultipleRemotesConnected_DoesNotDuplicateDataFromOneRemoteToOtherRemotes()
|
||||
{
|
||||
Assert.Fail();
|
||||
}
|
||||
|
||||
// PlayerConnection isn't connected in the editor and EditorConnection isn't connected
|
||||
// in players so we can't really test actual transport in just the application itself.
|
||||
// This will act as an IEditorPlayerConnection that immediately makes the FakePlayerConnection
|
||||
// on the other end receive messages.
|
||||
class FakePlayerConnection : IEditorPlayerConnection
|
||||
{
|
||||
public int playerId;
|
||||
// The fake connection acting as the socket on the opposite end of us.
|
||||
public FakePlayerConnection otherEnd;
|
||||
|
||||
public void Register(Guid messageId, UnityAction<MessageEventArgs> callback)
|
||||
{
|
||||
MessageEvent msgEvent;
|
||||
if (!m_MessageListeners.TryGetValue(messageId, out msgEvent))
|
||||
{
|
||||
msgEvent = new MessageEvent();
|
||||
m_MessageListeners[messageId] = msgEvent;
|
||||
}
|
||||
|
||||
msgEvent.AddListener(callback);
|
||||
}
|
||||
|
||||
public void Unregister(Guid messageId, UnityAction<MessageEventArgs> callback)
|
||||
{
|
||||
m_MessageListeners[messageId].RemoveListener(callback);
|
||||
}
|
||||
|
||||
public void DisconnectAll()
|
||||
{
|
||||
m_MessageListeners.Clear();
|
||||
m_ConnectionListeners.RemoveAllListeners();
|
||||
m_DisconnectionListeners.RemoveAllListeners();
|
||||
}
|
||||
|
||||
public void RegisterConnection(UnityAction<int> callback)
|
||||
{
|
||||
m_ConnectionListeners.AddListener(callback);
|
||||
}
|
||||
|
||||
public void RegisterDisconnection(UnityAction<int> callback)
|
||||
{
|
||||
m_DisconnectionListeners.AddListener(callback);
|
||||
}
|
||||
|
||||
public void Receive(Guid messageId, byte[] data)
|
||||
{
|
||||
MessageEvent msgEvent;
|
||||
if (m_MessageListeners.TryGetValue(messageId, out msgEvent))
|
||||
msgEvent.Invoke(new MessageEventArgs {playerId = playerId, data = data});
|
||||
}
|
||||
|
||||
public void Send(Guid messageId, byte[] data)
|
||||
{
|
||||
otherEnd.Receive(messageId, data);
|
||||
}
|
||||
|
||||
private Dictionary<Guid, MessageEvent> m_MessageListeners = new Dictionary<Guid, MessageEvent>();
|
||||
private ConnectEvent m_ConnectionListeners = new ConnectEvent();
|
||||
private ConnectEvent m_DisconnectionListeners = new ConnectEvent();
|
||||
private class MessageEvent : UnityEvent<MessageEventArgs>
|
||||
{
|
||||
}
|
||||
private class ConnectEvent : UnityEvent<int>
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class RemoteTestObserver : IObserver<InputRemoting.Message>
|
||||
{
|
||||
public List<InputRemoting.Message> messages = new List<InputRemoting.Message>();
|
||||
|
||||
public void OnNext(InputRemoting.Message msg)
|
||||
{
|
||||
messages.Add(msg);
|
||||
}
|
||||
|
||||
public void OnError(Exception error)
|
||||
{
|
||||
}
|
||||
|
||||
public void OnCompleted()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Category("Remote")]
|
||||
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.Connect(fakePlayerConnection);
|
||||
connectionToPlayer.Connect(fakeEditorConnection);
|
||||
|
||||
// Connect the local remote on the player side.
|
||||
InputSystem.remoting.Subscribe(connectionToEditor);
|
||||
InputSystem.remoting.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 templates and devices
|
||||
Assert.That(observer.messages, Has.Count.EqualTo(3));
|
||||
Assert.That(observer.messages[0].type, Is.EqualTo(InputRemoting.MessageType.NewDevice));
|
||||
Assert.That(observer.messages[1].type, Is.EqualTo(InputRemoting.MessageType.NewEvents));
|
||||
Assert.That(observer.messages[2].type, Is.EqualTo(InputRemoting.MessageType.RemoveDevice));
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
[Test]
|
||||
[Category("Editor")]
|
||||
|
@ -4680,3 +4820,4 @@ public class FunctionalTests : InputTestsBase
|
|||
Assert.Fail();
|
||||
}
|
||||
}
|
||||
#endif // DEVELOPMENT_BUILD || UNITY_EDITOR
|
||||
|
|
|
@ -2,38 +2,76 @@ namespace ISX
|
|||
{
|
||||
public static class CommonUsages
|
||||
{
|
||||
// Primary 2D motion control.
|
||||
// Example: left stick on gamepad.
|
||||
public static InternedString Primary2DMotion = new InternedString("Primary2DMotion");
|
||||
|
||||
// Secondary 2D motion control.
|
||||
// Example: right stick on gamepad.
|
||||
public static InternedString Secondary2DMotion = new InternedString("Secondary2DMotion");
|
||||
|
||||
public static InternedString PrimaryAction = new InternedString("PrimaryAction");
|
||||
public static InternedString SecondaryAction = new InternedString("SecondaryAction");
|
||||
public static InternedString PrimaryTrigger = new InternedString("PrimaryTrigger");
|
||||
public static InternedString SecondaryTrigger = new InternedString("SecondaryTrigger");
|
||||
public static InternedString Back = new InternedString("Back");
|
||||
public static InternedString Forward = new InternedString("Forward");
|
||||
public static InternedString Menu = new InternedString("Menu");
|
||||
public static InternedString Submit = new InternedString("Submit");////REVIEW: Call 'accept'?
|
||||
public static InternedString Cancel = new InternedString("Cancel");
|
||||
public static InternedString Previous = new InternedString("Previous");
|
||||
public static InternedString Next = new InternedString("Next");
|
||||
public static InternedString Modifier = new InternedString("Modifier"); // Stuff like CTRL
|
||||
public static InternedString ScrollHorizontal = new InternedString("ScrollHorizontal");
|
||||
public static InternedString Pressure = new InternedString("Pressure");
|
||||
public static InternedString Position = new InternedString("Position");
|
||||
public static InternedString Orientation = new InternedString("Orientation");
|
||||
public static InternedString Hatswitch = new InternedString("Hatswitch");
|
||||
|
||||
// Button to navigate to previous location.
|
||||
// Example: Escape on keyboard, B button on gamepad.
|
||||
public static InternedString Back = new InternedString("Back");
|
||||
|
||||
// Button to navigate to next location.
|
||||
public static InternedString Forward = new InternedString("Forward");
|
||||
|
||||
// Button to bring up menu.
|
||||
public static InternedString Menu = new InternedString("Menu");
|
||||
|
||||
// Button to confirm the current choice.
|
||||
public static InternedString Accept = new InternedString("Accept");
|
||||
|
||||
////REVIEW: isn't this the same as "Back"?
|
||||
// Button to not accept the current choice.
|
||||
public static InternedString Cancel = new InternedString("Cancel");
|
||||
|
||||
// Horizontal motion axis.
|
||||
// Example: X axis on mouse.
|
||||
public static InternedString Horizontal = new InternedString("Horizontal");
|
||||
|
||||
// Vertical motion axis.
|
||||
// Example: Y axis on mouse.
|
||||
public static InternedString Vertical = new InternedString("Vertical");
|
||||
|
||||
// Rotation around single, fixed axis.
|
||||
// Example: twist on joystick or twist of pen (few pens support that).
|
||||
public static InternedString Twist = new InternedString("Twist");
|
||||
|
||||
// Pressure level axis.
|
||||
// Example: pen pressure.
|
||||
public static InternedString Pressure = new InternedString("Pressure");
|
||||
|
||||
// Axis to scroll horizontally.
|
||||
public static InternedString ScrollHorizontal = new InternedString("ScrollHorizontal");
|
||||
|
||||
// Axis to scroll vertically.
|
||||
public static InternedString ScrollVertical = new InternedString("ScrollVertical");
|
||||
|
||||
public static InternedString Point = new InternedString("Point");
|
||||
|
||||
public static InternedString LowFreqMotor = new InternedString("LowFreqMotor");
|
||||
public static InternedString HighFreqMotor = new InternedString("HighFreqMotor");
|
||||
|
||||
// Device in left hand.
|
||||
// Example: left hand XR controller.
|
||||
public static InternedString LeftHand = new InternedString("LeftHand");
|
||||
|
||||
// Device in right hand.
|
||||
// Example: right hand XR controller.
|
||||
public static InternedString RightHand = new InternedString("RightHand");
|
||||
|
||||
// Axis representing charge of battery (1=full, 0=empty).
|
||||
public static InternedString BatteryStrength = new InternedString("BatteryStrength");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -100,6 +100,7 @@ namespace ISX
|
|||
|
||||
public virtual void SetConfiguration(ReadOnlyArray<Configuration> configuration)
|
||||
{
|
||||
//For native API, instead of sending actual string names for keys, CRC the keys and use ints for communication
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
namespace ISX
|
||||
{
|
||||
// If no module manager has been set up, this one is taken as a fallback.
|
||||
// Scans for all input modules present in the code and initializes any
|
||||
// that is compatible with the current runtime platform.
|
||||
public class DefaultInputModuleManager : IInputModuleManager
|
||||
{
|
||||
public void Initialize()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 7fd5d06ebb86414baed5cafa3aa761c6
|
||||
timeCreated: 1511228343
|
|
@ -15,6 +15,7 @@ namespace ISX
|
|||
|
||||
public InputDeviceDescription description => m_Description;
|
||||
|
||||
////REVIEW: on Xbox, a device can have multiple player IDs assigned to it
|
||||
////TODO: this needs to become part of the device's configuration
|
||||
// Systems that support multiple concurrent player inputs on the same system, the available
|
||||
// player inputs are usually numbered. For example, on a console the gamepads slots on the system
|
||||
|
|
|
@ -6,8 +6,13 @@ namespace ISX
|
|||
// input device-related assets in the project go into the build. The
|
||||
// imported asset corresponds to only the assets that get included
|
||||
// in the build for the current build target.
|
||||
public class InputDeviceDatabaseAsset : ScriptableObject
|
||||
public class InputDeviceDatabaseAsset : ScriptableObject, IInputModuleManager
|
||||
{
|
||||
public const string kExtension = "inputdevices";
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -105,7 +105,7 @@ namespace ISX
|
|||
[InputControl(name = "AnyKey", template = "AnyKey", sizeInBits = kSizeInBits)]
|
||||
[InputControl(name = "Escape", template = "Key", usages = new[] {"Back", "Cancel"}, bit = (int)Key.Escape)]
|
||||
[InputControl(name = "Space", template = "Key", bit = (int)Key.Space)]
|
||||
[InputControl(name = "Enter", template = "Key", usage = "Submit", bit = (int)Key.Enter)]
|
||||
[InputControl(name = "Enter", template = "Key", usage = "Accept", bit = (int)Key.Enter)]
|
||||
[InputControl(name = "Tab", template = "Key", bit = (int)Key.Tab)]
|
||||
[InputControl(name = "Backtick", template = "Key", bit = (int)Key.Backtick)]
|
||||
[InputControl(name = "Semicolon", template = "Key", bit = (int)Key.Semicolon)]
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
fileFormatVersion: 2
|
||||
guid: c5390a5185844de1abdba122ccdc5510
|
||||
timeCreated: 1511135240
|
|
@ -5,8 +5,6 @@ using System.Text;
|
|||
using UnityEngine;
|
||||
using UnityEngineInternal.Input;
|
||||
|
||||
////TODO: survive domain reloads
|
||||
|
||||
////TODO: reuse memory allocated for messages instead of allocating separately for each message
|
||||
|
||||
namespace ISX.Remote
|
||||
|
@ -66,6 +64,8 @@ namespace ISX.Remote
|
|||
m_LocalManager.onDeviceChange += SendDeviceChange;
|
||||
|
||||
m_IsSending = true;
|
||||
|
||||
SendAllCurrentDataToAllSubscribers();
|
||||
}
|
||||
|
||||
public void StopSending()
|
||||
|
@ -74,6 +74,7 @@ namespace ISX.Remote
|
|||
return;
|
||||
|
||||
m_LocalManager.onEvent -= SendEvent;
|
||||
m_LocalManager.onDeviceChange -= SendDeviceChange;
|
||||
|
||||
m_IsSending = false;
|
||||
}
|
||||
|
@ -82,6 +83,10 @@ namespace ISX.Remote
|
|||
{
|
||||
switch (msg.type)
|
||||
{
|
||||
case MessageType.Connect:
|
||||
break;
|
||||
case MessageType.Disconnect:
|
||||
break;
|
||||
case MessageType.NewTemplate:
|
||||
NewTemplateMsg.Process(this, msg);
|
||||
break;
|
||||
|
@ -116,12 +121,31 @@ namespace ISX.Remote
|
|||
var subscriber = new Subscriber {owner = this, observer = observer};
|
||||
ArrayHelpers.Append(ref m_Subscribers, subscriber);
|
||||
|
||||
SendAllTemplatesTo(subscriber);
|
||||
SendAllDevicesTo(subscriber);
|
||||
if (m_IsSending)
|
||||
SendAllCurrentDataToSubscriber(subscriber);
|
||||
|
||||
////REVIEW: Send connect?
|
||||
|
||||
return subscriber;
|
||||
}
|
||||
|
||||
// Let all subscribers know about all devices and templates that m_LocalManager has.
|
||||
private void SendAllCurrentDataToAllSubscribers()
|
||||
{
|
||||
if (m_Subscribers == null)
|
||||
return;
|
||||
|
||||
foreach (var subscriber in m_Subscribers)
|
||||
SendAllCurrentDataToSubscriber(subscriber);
|
||||
}
|
||||
|
||||
// Let the given subscriber know about all devices and templates that m_LocalManager has.
|
||||
private void SendAllCurrentDataToSubscriber(Subscriber subscriber)
|
||||
{
|
||||
SendAllTemplatesTo(subscriber);
|
||||
SendAllDevicesTo(subscriber);
|
||||
}
|
||||
|
||||
private void SendAllTemplatesTo(Subscriber subscriber)
|
||||
{
|
||||
var allTemplates = new List<string>();
|
||||
|
@ -186,6 +210,10 @@ namespace ISX.Remote
|
|||
if (m_Subscribers == null)
|
||||
return;
|
||||
|
||||
// Don't mirror remoted devices to other remotes.
|
||||
if (device.remote)
|
||||
return;
|
||||
|
||||
Message msg;
|
||||
switch (change)
|
||||
{
|
||||
|
@ -340,6 +368,8 @@ namespace ISX.Remote
|
|||
|
||||
public static Message Create(InputRemoting sender, InputDevice device)
|
||||
{
|
||||
Debug.Assert(!device.remote, "Device being sent to remotes should be a local devices, not a remote one");
|
||||
|
||||
var data = new Data
|
||||
{
|
||||
name = device.name,
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Networking.PlayerConnection;
|
||||
|
||||
namespace ISX.Remote
|
||||
|
@ -7,8 +8,12 @@ namespace ISX.Remote
|
|||
// make input on either side fully available on the other side. I.e. player
|
||||
// input can be fully debugged in the editor and editor input can conversely
|
||||
// be fed into the player.
|
||||
//
|
||||
// NOTE: The Unity EditorConnection/PlayerConnection mechanism requires this to
|
||||
// be a ScriptableObject as it will register every listeners as a persistent
|
||||
// one.
|
||||
[Serializable]
|
||||
internal class RemoteInputPlayerConnection : IObserver<InputRemoting.Message>, IObservable<InputRemoting.Message>
|
||||
internal class RemoteInputPlayerConnection : ScriptableObject, IObserver<InputRemoting.Message>, IObservable<InputRemoting.Message>
|
||||
{
|
||||
public static readonly Guid kNewDeviceMsg = new Guid("fcd9651ded40425995dfa6aeb78f1f1c");
|
||||
public static readonly Guid kNewTemplateMsg = new Guid("fccfec2b7369466d88502a9dd38505f4");
|
||||
|
@ -25,7 +30,11 @@ namespace ISX.Remote
|
|||
throw new InvalidOperationException("Already connected");
|
||||
}
|
||||
|
||||
// If there's already connections on the given IEditorPlayerConnection,
|
||||
// calling RegisterConnection() will invoke the given callback for every
|
||||
// already existing connection.
|
||||
connection.RegisterConnection(OnConnected);
|
||||
|
||||
connection.RegisterDisconnection(OnDisconnected);
|
||||
|
||||
connection.Register(kNewDeviceMsg, OnNewDevice);
|
||||
|
@ -33,34 +42,83 @@ namespace ISX.Remote
|
|||
connection.Register(kNewEventsMsg, OnNewEvents);
|
||||
connection.Register(kRemoveDeviceMsg, OnRemoveDevice);
|
||||
connection.Register(kChangeUsagesMsg, OnChangeUsages);
|
||||
|
||||
m_Connection = connection;
|
||||
}
|
||||
|
||||
public IDisposable Subscribe(IObserver<InputRemoting.Message> observer)
|
||||
{
|
||||
var subscriber = new Subscriber {owner = this, observer = observer};
|
||||
ArrayHelpers.Append(ref m_Subscribers, subscriber);
|
||||
|
||||
if (m_ConnectedIds != null)
|
||||
{
|
||||
foreach (var id in m_ConnectedIds)
|
||||
observer.OnNext(new InputRemoting.Message { type = InputRemoting.MessageType.Connect, sender = id });
|
||||
}
|
||||
|
||||
return subscriber;
|
||||
}
|
||||
|
||||
private void OnConnected(int id)
|
||||
{
|
||||
if (m_ConnectedIds != null && ArrayHelpers.Contains(m_ConnectedIds, id))
|
||||
return;
|
||||
|
||||
ArrayHelpers.Append(ref m_ConnectedIds, id);
|
||||
|
||||
SendToSubscribers(InputRemoting.MessageType.Connect, new MessageEventArgs {playerId = id});
|
||||
}
|
||||
|
||||
private void OnDisconnected(int id)
|
||||
{
|
||||
if (m_ConnectedIds == null || !ArrayHelpers.Contains(m_ConnectedIds, id))
|
||||
return;
|
||||
|
||||
ArrayHelpers.Erase(ref m_ConnectedIds, id);
|
||||
|
||||
SendToSubscribers(InputRemoting.MessageType.Disconnect, new MessageEventArgs {playerId = id});
|
||||
}
|
||||
|
||||
private void OnNewDevice(MessageEventArgs args)
|
||||
{
|
||||
SendToSubscribers(InputRemoting.MessageType.NewDevice, args);
|
||||
}
|
||||
|
||||
private void OnNewTemplate(MessageEventArgs args)
|
||||
{
|
||||
SendToSubscribers(InputRemoting.MessageType.NewTemplate, args);
|
||||
}
|
||||
|
||||
private void OnNewEvents(MessageEventArgs args)
|
||||
{
|
||||
SendToSubscribers(InputRemoting.MessageType.NewEvents, args);
|
||||
}
|
||||
|
||||
private void OnRemoveDevice(MessageEventArgs args)
|
||||
{
|
||||
SendToSubscribers(InputRemoting.MessageType.RemoveDevice, args);
|
||||
}
|
||||
|
||||
private void OnChangeUsages(MessageEventArgs args)
|
||||
{
|
||||
SendToSubscribers(InputRemoting.MessageType.ChangeUsages, args);
|
||||
}
|
||||
|
||||
private void SendToSubscribers(InputRemoting.MessageType type, MessageEventArgs args)
|
||||
{
|
||||
if (m_Subscribers == null)
|
||||
return;
|
||||
|
||||
var msg = new InputRemoting.Message
|
||||
{
|
||||
sender = args.playerId,
|
||||
type = type,
|
||||
data = args.data
|
||||
};
|
||||
|
||||
for (var i = 0; i < m_Subscribers.Length; ++i)
|
||||
m_Subscribers[i].observer.OnNext(msg);
|
||||
}
|
||||
|
||||
void IObserver<InputRemoting.Message>.OnNext(InputRemoting.Message msg)
|
||||
|
@ -96,21 +154,9 @@ namespace ISX.Remote
|
|||
{
|
||||
}
|
||||
|
||||
public IDisposable Subscribe(IObserver<InputRemoting.Message> observer)
|
||||
{
|
||||
var subscriber = new Subscriber {owner = this, observer = observer};
|
||||
ArrayHelpers.Append(ref m_Subscribers, subscriber);
|
||||
return subscriber;
|
||||
}
|
||||
|
||||
[NonSerialized] private IEditorPlayerConnection m_Connection;
|
||||
[NonSerialized] private Subscriber[] m_Subscribers;
|
||||
|
||||
[Serializable]
|
||||
private class Player
|
||||
{
|
||||
public int playerId;
|
||||
}
|
||||
[SerializeField] private int[] m_ConnectedIds;
|
||||
|
||||
private class Subscriber : IDisposable
|
||||
{
|
||||
|
@ -119,6 +165,7 @@ namespace ISX.Remote
|
|||
|
||||
public void Dispose()
|
||||
{
|
||||
ArrayHelpers.Erase(ref owner.m_Subscribers, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
namespace ISX
|
||||
{
|
||||
public interface IInputModuleManager
|
||||
{
|
||||
void Initialize();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 79a3ad6ec60e48feabae232b11acb573
|
||||
timeCreated: 1511228252
|
|
@ -15,7 +15,7 @@ using UnityEngineInternal.Input;
|
|||
namespace ISX
|
||||
{
|
||||
using DeviceChangeListener = Action<InputDevice, InputDeviceChange>;
|
||||
using DeviceDiscoveredListener = Func<InputDeviceDescription, string, string>;
|
||||
using DeviceFindTemplateListener = Func<InputDeviceDescription, string, string>;
|
||||
using EventListener = Action<InputEventPtr>;
|
||||
using UpdateListener = Action<InputUpdateType>;
|
||||
|
||||
|
@ -49,11 +49,10 @@ namespace ISX
|
|||
remove { m_DeviceChangeListeners.Remove(value); }
|
||||
}
|
||||
|
||||
////TODO: rename to onDeviceFindTemplate
|
||||
public event DeviceDiscoveredListener onDeviceDiscovered
|
||||
public event DeviceFindTemplateListener onFindTemplateForDevice
|
||||
{
|
||||
add { m_DeviceDiscoveredListeners.Append(value); }
|
||||
remove { m_DeviceDiscoveredListeners.Remove(value); }
|
||||
add { m_DeviceFindTemplateListeners.Append(value); }
|
||||
remove { m_DeviceFindTemplateListeners.Remove(value); }
|
||||
}
|
||||
|
||||
////TODO: add InputEventBuffer struct that uses NativeArray underneath
|
||||
|
@ -573,9 +572,9 @@ namespace ISX
|
|||
var template = TryFindMatchingTemplate(description);
|
||||
|
||||
// Give listeners a shot to select/create a template.
|
||||
for (var i = 0; i < m_DeviceDiscoveredListeners.Count; ++i)
|
||||
for (var i = 0; i < m_DeviceFindTemplateListeners.Count; ++i)
|
||||
{
|
||||
var newTemplate = m_DeviceDiscoveredListeners[i](description, template);
|
||||
var newTemplate = m_DeviceFindTemplateListeners[i](description, template);
|
||||
if (!string.IsNullOrEmpty(newTemplate))
|
||||
{
|
||||
template = newTemplate;
|
||||
|
@ -923,7 +922,7 @@ namespace ISX
|
|||
// Restoration of UnityActions is unreliable and it's too easy to end up with double
|
||||
// registrations what will lead to all kinds of misbehavior.
|
||||
[NonSerialized] private InlinedArray<DeviceChangeListener> m_DeviceChangeListeners;
|
||||
[NonSerialized] private InlinedArray<DeviceDiscoveredListener> m_DeviceDiscoveredListeners;
|
||||
[NonSerialized] private InlinedArray<DeviceFindTemplateListener> m_DeviceFindTemplateListeners;
|
||||
[NonSerialized] private InlinedArray<EventListener> m_EventListeners;
|
||||
[NonSerialized] private InlinedArray<UpdateListener> m_UpdateListeners;
|
||||
[NonSerialized] private bool m_NativeBeforeUpdateHooked;
|
||||
|
@ -1685,8 +1684,12 @@ namespace ISX
|
|||
#endif
|
||||
}
|
||||
|
||||
// Domain reload survival logic.
|
||||
#if UNITY_EDITOR
|
||||
// Domain reload survival logic. Also used for pushing and popping input system
|
||||
// state for testing.
|
||||
|
||||
// Stuff everything that we want to survive a domain reload into
|
||||
// a m_SerializedState.
|
||||
#if UNITY_EDITOR || DEVELOPMENT_BUILD
|
||||
[Serializable]
|
||||
internal struct DeviceState
|
||||
{
|
||||
|
@ -1777,7 +1780,7 @@ namespace ISX
|
|||
// across domain reloads. So we put them in here but don't serialize them (and
|
||||
// can't either except if we make them UnityEvents).
|
||||
[NonSerialized] public InlinedArray<DeviceChangeListener> deviceChangeListeners;
|
||||
[NonSerialized] public InlinedArray<DeviceDiscoveredListener> deviceDiscoveredListeners;
|
||||
[NonSerialized] public InlinedArray<DeviceFindTemplateListener> deviceDiscoveredListeners;
|
||||
[NonSerialized] public InlinedArray<EventListener> eventListeners;
|
||||
}
|
||||
|
||||
|
@ -1855,7 +1858,7 @@ namespace ISX
|
|||
buffers = m_StateBuffers,
|
||||
configuration = InputConfiguration.Save(),
|
||||
deviceChangeListeners = m_DeviceChangeListeners.Clone(),
|
||||
deviceDiscoveredListeners = m_DeviceDiscoveredListeners.Clone(),
|
||||
deviceDiscoveredListeners = m_DeviceFindTemplateListeners.Clone(),
|
||||
eventListeners = m_EventListeners.Clone(),
|
||||
updateMask = m_UpdateMask
|
||||
};
|
||||
|
@ -1875,7 +1878,7 @@ namespace ISX
|
|||
m_Devices = null;
|
||||
m_TemplateSetupVersion = state.templateSetupVersion + 1;
|
||||
m_DeviceChangeListeners = state.deviceChangeListeners;
|
||||
m_DeviceDiscoveredListeners = state.deviceDiscoveredListeners;
|
||||
m_DeviceFindTemplateListeners = state.deviceDiscoveredListeners;
|
||||
m_EventListeners = state.eventListeners;
|
||||
m_UpdateMask = state.updateMask;
|
||||
|
||||
|
@ -2011,6 +2014,8 @@ namespace ISX
|
|||
}
|
||||
m_Devices = devices;
|
||||
|
||||
////TODO: retry to make sense of available devices that we couldn't make sense of before; maybe we have a template now
|
||||
|
||||
// At the moment, there's no support for taking state across domain reloads
|
||||
// as we don't have support ATM for taking state across format changes.
|
||||
m_StateBuffers.FreeAll();
|
||||
|
@ -2020,8 +2025,8 @@ namespace ISX
|
|||
|
||||
[SerializeField] private SerializedState m_SerializedState;
|
||||
|
||||
// Stuff everything that we want to survive a domain reload into
|
||||
// a m_SerializedState.
|
||||
#endif // UNITY_EDITOR || DEVELOPMENT_BUILD
|
||||
#if UNITY_EDITOR
|
||||
void ISerializationCallbackReceiver.OnBeforeSerialize()
|
||||
{
|
||||
m_SerializedState = SaveState();
|
||||
|
|
|
@ -6,7 +6,7 @@ using System;
|
|||
|
||||
namespace ISX
|
||||
{
|
||||
public class InputPluginAttribute : Attribute
|
||||
public class InputModuleAttribute : Attribute
|
||||
{
|
||||
}
|
||||
}
|
|
@ -8,6 +8,8 @@ using UnityEngine;
|
|||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
using ISX.Editor;
|
||||
#else
|
||||
using UnityEngine.Networking.PlayerConnection;
|
||||
#endif
|
||||
|
||||
// I'd like to call the DLLs UnityEngine.Input and UnityEngine.Input.Tests
|
||||
|
@ -26,7 +28,9 @@ using ISX.Editor;
|
|||
|
||||
namespace ISX
|
||||
{
|
||||
// The primary API for the input system.
|
||||
/// <summary>
|
||||
/// This is the central API for the input system.
|
||||
/// </summary>
|
||||
// Takes care of the singletons we need and presents a sanitized API.
|
||||
#if UNITY_EDITOR
|
||||
[InitializeOnLoad]
|
||||
|
@ -145,10 +149,10 @@ namespace ISX
|
|||
remove { s_Manager.onDeviceChange -= value; }
|
||||
}
|
||||
|
||||
public static event Func<InputDeviceDescription, string, string> onDeviceDiscovered
|
||||
public static event Func<InputDeviceDescription, string, string> onFindTemplateForDevice
|
||||
{
|
||||
add { s_Manager.onDeviceDiscovered += value; }
|
||||
remove { s_Manager.onDeviceDiscovered -= value; }
|
||||
add { s_Manager.onFindTemplateForDevice += value; }
|
||||
remove { s_Manager.onFindTemplateForDevice -= value; }
|
||||
}
|
||||
|
||||
public static InputDevice AddDevice(string template, string name = null)
|
||||
|
@ -454,7 +458,7 @@ namespace ISX
|
|||
|
||||
#region Remoting
|
||||
|
||||
public static InputRemoting remote
|
||||
public static InputRemoting remoting
|
||||
{
|
||||
get
|
||||
{
|
||||
|
@ -475,13 +479,10 @@ namespace ISX
|
|||
internal static InputManager s_Manager;
|
||||
internal static InputRemoting s_Remote;
|
||||
|
||||
|
||||
// The rest here is internal stuff to manage singletons, survive domain reloads,
|
||||
// and to support the reset ability for tests.
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private static bool s_Initialized;
|
||||
private static InputSystemObject s_SystemObject;
|
||||
|
||||
static InputSystem()
|
||||
{
|
||||
// Unity's InitializeOnLoad force-executes static class constructors without
|
||||
|
@ -494,6 +495,20 @@ namespace ISX
|
|||
if (s_Initialized)
|
||||
return;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
InitializeInEditor();
|
||||
#else
|
||||
InitializeInPlayer();
|
||||
#endif
|
||||
|
||||
s_Initialized = true;
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private static InputSystemObject s_SystemObject;
|
||||
|
||||
private static void InitializeInEditor()
|
||||
{
|
||||
var existingSystemObjects = Resources.FindObjectsOfTypeAll<InputSystemObject>();
|
||||
if (existingSystemObjects != null && existingSystemObjects.Length > 0)
|
||||
{
|
||||
|
@ -509,17 +524,6 @@ namespace ISX
|
|||
}
|
||||
|
||||
EditorApplication.playModeStateChanged += OnPlayModeChange;
|
||||
|
||||
s_Initialized = true;
|
||||
}
|
||||
|
||||
internal static void Reset()
|
||||
{
|
||||
if (s_SystemObject != null)
|
||||
UnityEngine.Object.DestroyImmediate(s_SystemObject);
|
||||
s_SystemObject = ScriptableObject.CreateInstance<InputSystemObject>();
|
||||
s_Manager = s_SystemObject.manager;
|
||||
s_Remote = s_SystemObject.remote;
|
||||
}
|
||||
|
||||
// We don't want play mode modifications to templates and controls to seep
|
||||
|
@ -542,6 +546,58 @@ namespace ISX
|
|||
}
|
||||
}
|
||||
|
||||
#else
|
||||
#if DEVELOPMENT_BUILD
|
||||
private static RemoteInputPlayerConnection s_RemoteEditorConnection;
|
||||
#endif
|
||||
|
||||
[RuntimeInitializeOnLoadMethod(loadType: RuntimeInitializeLoadType.BeforeSceneLoad)]
|
||||
public static void InitializeInPlayer()
|
||||
{
|
||||
if (s_Initialized)
|
||||
return;
|
||||
|
||||
// No domain reloads in the player so we don't need to look for existing
|
||||
// instances.
|
||||
s_Manager = new InputManager();
|
||||
s_Manager.Initialize();
|
||||
|
||||
////TODO: put this behind a switch so that it is off by default
|
||||
// Automatically enable remoting in development players.
|
||||
#if DEVELOPMENT_BUILD
|
||||
s_Remote = new InputRemoting(s_Manager);
|
||||
s_RemoteEditorConnection = ScriptableObject.CreateInstance<RemoteInputPlayerConnection>();
|
||||
s_RemoteEditorConnection.Connect(PlayerConnection.instance);
|
||||
s_Remote.Subscribe(s_RemoteEditorConnection);
|
||||
s_RemoteEditorConnection.Subscribe(s_Remote);
|
||||
s_Remote.StartSending();
|
||||
#endif
|
||||
|
||||
s_Initialized = true;
|
||||
}
|
||||
|
||||
#endif // UNITY_EDITOR
|
||||
|
||||
// For testing, we want the ability to push/pop system state even in the player.
|
||||
// However, we don't want it in release players.
|
||||
#if DEVELOPMENT_BUILD || UNITY_EDITOR
|
||||
internal static void Reset()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
if (s_SystemObject != null)
|
||||
UnityEngine.Object.DestroyImmediate(s_SystemObject);
|
||||
s_SystemObject = ScriptableObject.CreateInstance<InputSystemObject>();
|
||||
s_Manager = s_SystemObject.manager;
|
||||
s_Remote = s_SystemObject.remote;
|
||||
#else
|
||||
if (s_Manager != null)
|
||||
s_Manager.Destroy();
|
||||
////TODO: reset remote
|
||||
s_Initialized = false;
|
||||
InitializeInPlayer();
|
||||
#endif
|
||||
}
|
||||
|
||||
private static List<InputManager.SerializedState> s_SerializedStateStack;
|
||||
|
||||
////REVIEW: what should we do with the remote here?
|
||||
|
@ -564,29 +620,6 @@ namespace ISX
|
|||
}
|
||||
}
|
||||
|
||||
#else
|
||||
#if DEVELOPMENT_BUILD
|
||||
private static RemoteInputNetworkTransportToEditor s_RemoteEditorConnection;
|
||||
#endif
|
||||
|
||||
[RuntimeInitializeOnLoadMethod(loadType: RuntimeInitializeLoadType.BeforeSceneLoad)]
|
||||
public static void InitializeInPlayer()
|
||||
{
|
||||
// No domain reloads in the player so we don't need to look for existing
|
||||
// instances.
|
||||
s_Manager = new InputManager();
|
||||
|
||||
////TODO: put this behind a switch so that it is off by default
|
||||
// Automatically enable remoting in development players.
|
||||
#if DEVELOPMENT_BUILD
|
||||
s_Remote = new InputRemoting(s_Manager);
|
||||
s_RemoteEditorConnection = new RemoteInputNetworkTransportToEditor();
|
||||
s_Remote.Subscribe(s_RemoteEditorConnection);
|
||||
s_RemoteEditorConnection.Subscribe(s_Remote);
|
||||
s_Remote.StartSending();
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ namespace ISX
|
|||
{
|
||||
[SerializeField] public InputManager manager;
|
||||
[NonSerialized] public InputRemoting remote;
|
||||
[SerializeField] public RemoteInputPlayerConnection playerConnections;
|
||||
[SerializeField] public RemoteInputPlayerConnection playerConnection;
|
||||
|
||||
[SerializeField] private InputRemoting.SerializedState m_RemotingState;
|
||||
|
||||
|
@ -26,7 +26,6 @@ namespace ISX
|
|||
manager.Initialize();
|
||||
|
||||
// In the editor, we always set up for remoting.
|
||||
playerConnections = new RemoteInputPlayerConnection();
|
||||
SetUpRemoting();
|
||||
}
|
||||
|
||||
|
@ -40,8 +39,12 @@ namespace ISX
|
|||
{
|
||||
remote = new InputRemoting(manager, m_RemotingState.senderId);
|
||||
remote.RestoreState(m_RemotingState, manager);
|
||||
remote.Subscribe(playerConnections); // Feed messages from players into editor.
|
||||
playerConnections.Subscribe(remote); // Feed messages from editor into players.
|
||||
|
||||
if (playerConnection == null)
|
||||
playerConnection = CreateInstance<RemoteInputPlayerConnection>();
|
||||
|
||||
remote.Subscribe(playerConnection); // Feed messages from players into editor.
|
||||
playerConnection.Subscribe(remote); // Feed messages from editor into players.
|
||||
|
||||
// We don't enable sending on the editor's remote by default.
|
||||
// By default, the editor acts as a receiver only.
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#if DEVELOPMENT_BUILD || UNITY_EDITOR
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace ISX
|
||||
|
@ -21,9 +22,11 @@ namespace ISX
|
|||
// none of the native devices.
|
||||
InputSystem.Reset();
|
||||
|
||||
#if UNITY_EDITOR
|
||||
// Make sure we're not affected by the user giving focus away from the
|
||||
// game view.
|
||||
InputConfiguration.LockInputToGame = true;
|
||||
#endif
|
||||
|
||||
if (InputSystem.devices.Count > 0)
|
||||
Assert.Fail("Input system should not have devices after reset");
|
||||
|
@ -42,3 +45,4 @@ namespace ISX
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif // DEVELOPMENT_BUILD || UNITY_EDITOR
|
||||
|
|
|
@ -3,20 +3,21 @@
|
|||
--- !u!129 &1
|
||||
PlayerSettings:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 14
|
||||
serializedVersion: 15
|
||||
productGUID: 97965645ae37e47c485fb153bcb9de86
|
||||
AndroidProfiler: 0
|
||||
AndroidFilterTouchesWhenObscured: 0
|
||||
AndroidEnableSustainedPerformanceMode: 0
|
||||
defaultScreenOrientation: 4
|
||||
targetDevice: 2
|
||||
useOnDemandResources: 0
|
||||
accelerometerFrequency: 60
|
||||
companyName: DefaultCompany
|
||||
productName: InputSystemX
|
||||
productName: UnityTestFramework
|
||||
defaultCursor: {fileID: 0}
|
||||
cursorHotspot: {x: 0, y: 0}
|
||||
m_SplashScreenBackgroundColor: {r: 0.13725491, g: 0.12156863, b: 0.1254902, a: 1}
|
||||
m_ShowUnitySplashScreen: 1
|
||||
m_ShowUnitySplashScreen: 0
|
||||
m_ShowUnitySplashLogo: 1
|
||||
m_SplashScreenOverlayOpacity: 1
|
||||
m_SplashScreenAnimation: 1
|
||||
|
@ -53,7 +54,7 @@ PlayerSettings:
|
|||
androidShowActivityIndicatorOnLoading: -1
|
||||
tizenShowActivityIndicatorOnLoading: -1
|
||||
iosAppInBackgroundBehavior: 0
|
||||
displayResolutionDialog: 1
|
||||
displayResolutionDialog: 0
|
||||
iosAllowHTTPDownload: 1
|
||||
allowedAutorotateToPortrait: 1
|
||||
allowedAutorotateToPortraitUpsideDown: 1
|
||||
|
@ -72,11 +73,13 @@ PlayerSettings:
|
|||
muteOtherAudioSources: 0
|
||||
Prepare IOS For Recording: 0
|
||||
Force IOS Speakers When Recording: 0
|
||||
deferSystemGesturesMode: 0
|
||||
hideHomeButton: 0
|
||||
submitAnalytics: 1
|
||||
usePlayerLog: 1
|
||||
bakeCollisionMeshes: 0
|
||||
forceSingleInstance: 0
|
||||
resizableWindow: 0
|
||||
resizableWindow: 1
|
||||
useMacAppStoreValidation: 0
|
||||
macAppStoreCategory: public.app-category.games
|
||||
gpuSkinning: 0
|
||||
|
@ -89,7 +92,7 @@ PlayerSettings:
|
|||
visibleInBackground: 1
|
||||
allowFullscreenSwitch: 1
|
||||
graphicsJobMode: 0
|
||||
fullscreenMode: 1
|
||||
fullscreenMode: 3
|
||||
xboxSpeechDB: 0
|
||||
xboxEnableHeadOrientation: 0
|
||||
xboxEnableGuest: 0
|
||||
|
@ -99,6 +102,8 @@ PlayerSettings:
|
|||
n3dsEnableSharedListOpt: 1
|
||||
n3dsEnableVSync: 0
|
||||
xboxOneResolution: 0
|
||||
xboxOneSResolution: 0
|
||||
xboxOneXResolution: 3
|
||||
xboxOneMonoLoggingLevel: 0
|
||||
xboxOneLoggingLevel: 1
|
||||
xboxOneDisableEsram: 0
|
||||
|
@ -154,7 +159,7 @@ PlayerSettings:
|
|||
AndroidMinSdkVersion: 16
|
||||
AndroidTargetSdkVersion: 0
|
||||
AndroidPreferredInstallLocation: 1
|
||||
aotOptions:
|
||||
aotOptions: nimt-trampolines=1024
|
||||
stripEngineCode: 1
|
||||
iPhoneStrippingLevel: 0
|
||||
iPhoneScriptCallOptimization: 0
|
||||
|
@ -184,15 +189,22 @@ PlayerSettings:
|
|||
iPhone47inSplashScreen: {fileID: 0}
|
||||
iPhone55inPortraitSplashScreen: {fileID: 0}
|
||||
iPhone55inLandscapeSplashScreen: {fileID: 0}
|
||||
iPhone58inPortraitSplashScreen: {fileID: 0}
|
||||
iPhone58inLandscapeSplashScreen: {fileID: 0}
|
||||
iPadPortraitSplashScreen: {fileID: 0}
|
||||
iPadHighResPortraitSplashScreen: {fileID: 0}
|
||||
iPadLandscapeSplashScreen: {fileID: 0}
|
||||
iPadHighResLandscapeSplashScreen: {fileID: 0}
|
||||
appleTVSplashScreen: {fileID: 0}
|
||||
appleTVSplashScreen2x: {fileID: 0}
|
||||
tvOSSmallIconLayers: []
|
||||
tvOSSmallIconLayers2x: []
|
||||
tvOSLargeIconLayers: []
|
||||
tvOSLargeIconLayers2x: []
|
||||
tvOSTopShelfImageLayers: []
|
||||
tvOSTopShelfImageLayers2x: []
|
||||
tvOSTopShelfImageWideLayers: []
|
||||
tvOSTopShelfImageWideLayers2x: []
|
||||
iOSLaunchScreenType: 0
|
||||
iOSLaunchScreenPortrait: {fileID: 0}
|
||||
iOSLaunchScreenLandscape: {fileID: 0}
|
||||
|
@ -223,8 +235,10 @@ PlayerSettings:
|
|||
iOSManualSigningProvisioningProfileID:
|
||||
tvOSManualSigningProvisioningProfileID:
|
||||
appleEnableAutomaticSigning: 0
|
||||
iOSRequireARKit: 0
|
||||
appleEnableProMotion: 0
|
||||
clonedFromGUID: 00000000000000000000000000000000
|
||||
AndroidTargetDevice: 0
|
||||
AndroidTargetArchitectures: 5
|
||||
AndroidSplashScreenScale: 0
|
||||
androidSplashScreen: {fileID: 0}
|
||||
AndroidKeystoreName:
|
||||
|
@ -305,6 +319,9 @@ PlayerSettings:
|
|||
switchTitleNames_9:
|
||||
switchTitleNames_10:
|
||||
switchTitleNames_11:
|
||||
switchTitleNames_12:
|
||||
switchTitleNames_13:
|
||||
switchTitleNames_14:
|
||||
switchPublisherNames_0:
|
||||
switchPublisherNames_1:
|
||||
switchPublisherNames_2:
|
||||
|
@ -317,6 +334,9 @@ PlayerSettings:
|
|||
switchPublisherNames_9:
|
||||
switchPublisherNames_10:
|
||||
switchPublisherNames_11:
|
||||
switchPublisherNames_12:
|
||||
switchPublisherNames_13:
|
||||
switchPublisherNames_14:
|
||||
switchIcons_0: {fileID: 0}
|
||||
switchIcons_1: {fileID: 0}
|
||||
switchIcons_2: {fileID: 0}
|
||||
|
@ -329,6 +349,9 @@ PlayerSettings:
|
|||
switchIcons_9: {fileID: 0}
|
||||
switchIcons_10: {fileID: 0}
|
||||
switchIcons_11: {fileID: 0}
|
||||
switchIcons_12: {fileID: 0}
|
||||
switchIcons_13: {fileID: 0}
|
||||
switchIcons_14: {fileID: 0}
|
||||
switchSmallIcons_0: {fileID: 0}
|
||||
switchSmallIcons_1: {fileID: 0}
|
||||
switchSmallIcons_2: {fileID: 0}
|
||||
|
@ -341,6 +364,9 @@ PlayerSettings:
|
|||
switchSmallIcons_9: {fileID: 0}
|
||||
switchSmallIcons_10: {fileID: 0}
|
||||
switchSmallIcons_11: {fileID: 0}
|
||||
switchSmallIcons_12: {fileID: 0}
|
||||
switchSmallIcons_13: {fileID: 0}
|
||||
switchSmallIcons_14: {fileID: 0}
|
||||
switchManualHTML:
|
||||
switchAccessibleURLs:
|
||||
switchLegalInformation:
|
||||
|
@ -382,6 +408,8 @@ PlayerSettings:
|
|||
switchLocalCommunicationIds_7:
|
||||
switchParentalControl: 0
|
||||
switchAllowsScreenshot: 1
|
||||
switchAllowsVideoCapturing: 1
|
||||
switchAllowsRuntimeAddOnContentInstall: 0
|
||||
switchDataLossConfirmation: 0
|
||||
switchSupportedNpadStyles: 3
|
||||
switchSocketConfigEnabled: 0
|
||||
|
@ -439,6 +467,7 @@ PlayerSettings:
|
|||
ps4pnFriends: 1
|
||||
ps4pnGameCustomData: 1
|
||||
playerPrefsSupport: 0
|
||||
enableApplicationExit: 0
|
||||
restrictedAudioUsageRights: 0
|
||||
ps4UseResolutionFallback: 0
|
||||
ps4ReprojectionSupport: 0
|
||||
|
@ -523,8 +552,8 @@ PlayerSettings:
|
|||
webGLTemplate: APPLICATION:Default
|
||||
webGLAnalyzeBuildSize: 0
|
||||
webGLUseEmbeddedResources: 0
|
||||
webGLUseWasm: 0
|
||||
webGLCompressionFormat: 1
|
||||
webGLLinkerTarget: 0
|
||||
scriptingDefineSymbols: {}
|
||||
platformArchitecture: {}
|
||||
scriptingBackend: {}
|
||||
|
|
Загрузка…
Ссылка в новой задаче