InputRemoting.cs 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866
  1. // note:: This script is using code snippets in InputSystem.
  2. // https://github.com/Unity-Technologies/InputSystem/blob/develop/Packages/com.unity.inputsystem/InputSystem/Devices/Remote/InputRemoting.cs
  3. using System;
  4. using System.Linq;
  5. using System.Runtime.InteropServices;
  6. using System.Text;
  7. using Unity.Collections.LowLevel.Unsafe;
  8. using UnityEngine;
  9. using UnityEngine.InputSystem.Layouts;
  10. using UnityEngine.InputSystem.LowLevel;
  11. using UnityEngine.InputSystem.Utilities;
  12. using UnityEngine.InputSystem;
  13. ////TODO: show remote device IDs in the debugger
  14. ////TODO: remote timestamps need to be translated to local timestamps; doesn't make sense for remote events getting
  15. //// processed on the local timeline as is when the originating timeline may be quite different
  16. ////TODO: support actions
  17. ////TODO: support input users
  18. ////TODO: text input events
  19. ////REVIEW: it seems that the various XXXMsg struct should be public; ATM doesn't seem like working with the message interface is practical
  20. ////REVIEW: the namespacing mechanism for layouts which changes base layouts means that layouts can't be played
  21. //// around with on the editor side but will only be changed once they're updated in the player
  22. namespace Unity.RenderStreaming.InputSystem
  23. {
  24. /// <summary>
  25. /// Makes the activity and data of an InputManager observable in message form.
  26. /// </summary>
  27. /// <remarks>
  28. /// Can act as both the sender and Receiver of these message so the flow is fully bidirectional,
  29. /// i.e. the InputManager on either end can mirror its layouts, devices, and events over
  30. /// to the other end. This permits streaming input not just from the player to the editor but
  31. /// also feeding input from the editor back into the player.
  32. ///
  33. /// Remoting sits entirely on top of the input system as an optional piece of functionality.
  34. /// In development players and the editor, we enable it automatically but in non-development
  35. /// players it has to be explicitly requested by the user.
  36. ///
  37. /// To see devices and input from players in the editor, open the Input Debugger through
  38. /// "Windows >> Input Debugger".
  39. /// </remarks>
  40. /// <seealso cref="InputSystem.remoting"/>
  41. /// \todo Reuse memory allocated for messages instead of allocating separately for each message.
  42. /// \todo Inteface to determine what to mirror from the local manager to the remote system.
  43. public sealed class InputRemoting : IObservable<InputRemoting.Message>, IObserver<InputRemoting.Message>
  44. {
  45. /// <summary>
  46. /// Enumeration of possible types of messages exchanged between two InputRemoting instances.
  47. /// </summary>
  48. public enum MessageType
  49. {
  50. Connect,
  51. Disconnect,
  52. NewLayout,
  53. NewDevice,
  54. NewEvents,
  55. RemoveDevice,
  56. RemoveLayout,
  57. ChangeUsages,
  58. StartSending,
  59. StopSending,
  60. NewOtherMessage,
  61. }
  62. /// <summary>
  63. /// A message exchanged between two InputRemoting instances.
  64. /// </summary>
  65. [StructLayout(LayoutKind.Sequential)]
  66. public struct Message
  67. {
  68. /// <summary>
  69. /// For messages coming in, numeric ID of the sender of the message. For messages
  70. /// going out, numeric ID of the targeted Receiver of the message.
  71. /// </summary>
  72. public int participantId;
  73. public MessageType type;
  74. public byte[] data;
  75. }
  76. public bool sending
  77. {
  78. get => (m_Flags & Flags.Sending) == Flags.Sending;
  79. private set
  80. {
  81. if (value)
  82. m_Flags |= Flags.Sending;
  83. else
  84. m_Flags &= ~Flags.Sending;
  85. }
  86. }
  87. static InputRemoting()
  88. {
  89. #if UNITY_EDITOR
  90. //
  91. // note: This lines are for avoiding issues when running the editor
  92. // on background. When moved the focus from the editor, input events
  93. // from another process are ignored.
  94. // Please attention behaviours are difference several platforms when
  95. // moving focus from Unity Editor.
  96. //
  97. // Additionally, The behaviour is changed Unity2021.2 later (using
  98. // InputSystem 1.1). Please see "Background behaviour".
  99. // https://docs.unity3d.com/Packages/com.unity.inputsystem@1.1/manual/Settings.html#background-behavior
  100. #if INPUTSYSTEM_1_1_OR_NEWER
  101. // todo(kazuki):
  102. #else
  103. // Make sure we're not affected by the user giving focus away from the
  104. // game view.
  105. //
  106. InputEditorUserSettings.lockInputToGameView = true;
  107. #endif
  108. #endif
  109. }
  110. internal InputRemoting(IInputManager manager, bool startSendingOnConnect = false)
  111. {
  112. if (manager == null)
  113. throw new ArgumentNullException("manager");
  114. m_LocalManager = manager;
  115. if (startSendingOnConnect)
  116. m_Flags |= Flags.StartSendingOnConnect;
  117. //when listening for newly added layouts, must filter out ones we've added from remote
  118. }
  119. /// <summary>
  120. /// Start sending messages for data and activity in the local input system
  121. /// to observers.
  122. /// </summary>
  123. /// <seealso cref="sending"/>
  124. /// <seealso cref="StopSending"/>
  125. public void StartSending()
  126. {
  127. if (sending)
  128. return;
  129. ////TODO: send events in bulk rather than one-by-one
  130. m_LocalManager.onMessage += Send;
  131. m_LocalManager.onEvent += SendEvent;
  132. m_LocalManager.onDeviceChange += SendDeviceChange;
  133. m_LocalManager.onLayoutChange += SendLayoutChange;
  134. sending = true;
  135. SendInitialMessages();
  136. }
  137. public void StopSending()
  138. {
  139. if (!sending)
  140. return;
  141. m_LocalManager.onMessage -= Send;
  142. m_LocalManager.onEvent -= SendEvent;
  143. m_LocalManager.onDeviceChange -= SendDeviceChange;
  144. m_LocalManager.onLayoutChange -= SendLayoutChange;
  145. sending = false;
  146. }
  147. //RTC 接收到的Message(接收端)
  148. void IObserver<Message>.OnNext(Message msg)
  149. {
  150. switch (msg.type)
  151. {
  152. case MessageType.Connect:
  153. ConnectMsg.Process(this);
  154. break;
  155. case MessageType.Disconnect:
  156. DisconnectMsg.Process(this, msg);
  157. break;
  158. case MessageType.NewLayout:
  159. NewLayoutMsg.Process(this, msg);
  160. break;
  161. case MessageType.RemoveLayout:
  162. RemoveLayoutMsg.Process(this, msg);
  163. break;
  164. case MessageType.NewDevice:
  165. NewDeviceMsg.Process(this, msg);
  166. break;
  167. case MessageType.NewEvents:
  168. NewEventsMsg.Process(this, msg);
  169. break;
  170. case MessageType.ChangeUsages:
  171. ChangeUsageMsg.Process(this, msg);
  172. break;
  173. case MessageType.RemoveDevice:
  174. RemoveDeviceMsg.Process(this, msg);
  175. break;
  176. case MessageType.StartSending:
  177. StartSendingMsg.Process(this);
  178. break;
  179. case MessageType.StopSending:
  180. StopSendingMsg.Process(this);
  181. break;
  182. case MessageType.NewOtherMessage:
  183. Debug.Log("NewOtherMessage===>"+ Encoding.UTF8.GetString(msg.data));
  184. break;
  185. }
  186. }
  187. void IObserver<Message>.OnError(Exception error)
  188. {
  189. }
  190. void IObserver<Message>.OnCompleted()
  191. {
  192. }
  193. public IDisposable Subscribe(IObserver<Message> observer)
  194. {
  195. if (observer == null)
  196. throw new ArgumentNullException("observer");
  197. var subscriber = new Subscriber { owner = this, observer = observer };
  198. ArrayHelpers.Append(ref m_Subscribers, subscriber);
  199. return subscriber;
  200. }
  201. private void SendInitialMessages()
  202. {
  203. SendAllGeneratedLayouts();
  204. SendAllDevices();
  205. }
  206. private void SendAllGeneratedLayouts()
  207. {
  208. // todo(kazuki)::
  209. // layputBuilders property is not published from InputSystem
  210. //
  211. //foreach (var entry in m_LocalManager.m_Layouts.layoutBuilders)
  212. // SendLayout(entry.Key);
  213. foreach (var layout in m_LocalManager.layouts)
  214. SendLayout(layout);
  215. }
  216. private void SendLayout(string layoutName)
  217. {
  218. if (m_Subscribers == null)
  219. return;
  220. var message = NewLayoutMsg.Create(this, layoutName);
  221. if (message != null)
  222. Send(message.Value);
  223. }
  224. private void SendAllDevices()
  225. {
  226. var devices = m_LocalManager.devices;
  227. foreach (var device in devices)
  228. SendDevice(device);
  229. }
  230. private void SendDevice(InputDevice device)
  231. {
  232. if (m_Subscribers == null)
  233. return;
  234. // Don't mirror remote devices to other remotes.
  235. if (device.remote)
  236. return;
  237. var newDeviceMessage = NewDeviceMsg.Create(device);
  238. Send(newDeviceMessage);
  239. // Send current state. We do this here in this case as the device
  240. // may have been added some time ago and thus have already received events.
  241. var stateEventMessage = NewEventsMsg.CreateStateEvent(device);
  242. Send(stateEventMessage);
  243. }
  244. private unsafe void SendEvent(InputEventPtr eventPtr, InputDevice device)
  245. {
  246. if (m_Subscribers == null)
  247. return;
  248. ////REVIEW: we probably want to have better control over this and allow producing local events
  249. //// against remote devices which *are* indeed sent across the wire
  250. // Don't send events that came in from remote devices.
  251. if (device != null && device.remote)
  252. return;
  253. var message = NewEventsMsg.Create(eventPtr.data, 1);
  254. Debug.Log("SendEvent==>" + Encoding.UTF8.GetString(message.data));
  255. Send(message);
  256. }
  257. private void SendDeviceChange(InputDevice device, InputDeviceChange change)
  258. {
  259. if (m_Subscribers == null)
  260. return;
  261. // Don't mirror remoted devices to other remotes.
  262. if (device.remote)
  263. return;
  264. Message msg;
  265. switch (change)
  266. {
  267. case InputDeviceChange.Added:
  268. msg = NewDeviceMsg.Create(device);
  269. break;
  270. case InputDeviceChange.Removed:
  271. msg = RemoveDeviceMsg.Create(device);
  272. break;
  273. case InputDeviceChange.UsageChanged:
  274. msg = ChangeUsageMsg.Create(device);
  275. break;
  276. default:
  277. return;
  278. }
  279. Send(msg);
  280. }
  281. private void SendLayoutChange(string layout, InputControlLayoutChange change)
  282. {
  283. if (m_Subscribers == null)
  284. return;
  285. Message msg;
  286. switch (change)
  287. {
  288. case InputControlLayoutChange.Added:
  289. case InputControlLayoutChange.Replaced:
  290. var message = NewLayoutMsg.Create(this, layout);
  291. if (message == null)
  292. return;
  293. msg = message.Value;
  294. break;
  295. case InputControlLayoutChange.Removed:
  296. msg = RemoveLayoutMsg.Create(layout);
  297. break;
  298. default:
  299. return;
  300. }
  301. Send(msg);
  302. }
  303. public void Send(Message msg)
  304. {
  305. foreach (var subscriber in m_Subscribers)
  306. subscriber.observer.OnNext(msg);
  307. }
  308. ////TODO: with C#7 this should be a ref return
  309. private int FindOrCreateSenderRecord(int senderId)
  310. {
  311. // Try to find existing.
  312. if (m_Senders != null)
  313. {
  314. var senderCount = m_Senders.Length;
  315. for (var i = 0; i < senderCount; ++i)
  316. if (m_Senders[i].senderId == senderId)
  317. return i;
  318. }
  319. // Create new.
  320. var sender = new RemoteSender
  321. {
  322. senderId = senderId,
  323. };
  324. return ArrayHelpers.Append(ref m_Senders, sender);
  325. }
  326. private int FindLocalDeviceId(int remoteDeviceId, int senderIndex)
  327. {
  328. var localDevices = m_Senders[senderIndex].devices;
  329. if (localDevices != null)
  330. {
  331. var numLocalDevices = localDevices.Length;
  332. for (var i = 0; i < numLocalDevices; ++i)
  333. {
  334. if (localDevices[i].remoteId == remoteDeviceId)
  335. return localDevices[i].localId;
  336. }
  337. }
  338. return InputDevice.InvalidDeviceId;
  339. }
  340. private InputDevice TryGetDeviceByRemoteId(int remoteDeviceId, int senderIndex)
  341. {
  342. var localId = FindLocalDeviceId(remoteDeviceId, senderIndex);
  343. return m_LocalManager.GetDeviceById(localId);
  344. }
  345. private Flags m_Flags;
  346. private IInputManager m_LocalManager; // Input system we mirror input from and to.
  347. private Subscriber[] m_Subscribers; // Receivers we send input to.
  348. private RemoteSender[] m_Senders; // Senders we receive input from.
  349. [Flags]
  350. private enum Flags
  351. {
  352. Sending = 1 << 0,
  353. StartSendingOnConnect = 1 << 1
  354. }
  355. // Data we keep about a unique sender that we receive input data
  356. // from. We keep track of the layouts and devices we added to
  357. // the local system.
  358. [Serializable]
  359. internal struct RemoteSender
  360. {
  361. public int senderId;
  362. public string[] layouts;
  363. public RemoteInputDevice[] devices;
  364. }
  365. [Serializable]
  366. internal struct RemoteInputDevice
  367. {
  368. public int remoteId; // Device ID used by sender.
  369. public int localId; // Device ID used by us in local system.
  370. public InputDeviceDescription description;
  371. }
  372. internal class Subscriber : IDisposable
  373. {
  374. public InputRemoting owner;
  375. public IObserver<Message> observer;
  376. public void Dispose()
  377. {
  378. ArrayHelpers.Erase(ref owner.m_Subscribers, this);
  379. }
  380. }
  381. private static class ConnectMsg
  382. {
  383. public static void Process(InputRemoting Receiver)
  384. {
  385. if (Receiver.sending)
  386. {
  387. Receiver.SendAllDevices();
  388. }
  389. else if ((Receiver.m_Flags & Flags.StartSendingOnConnect) == Flags.StartSendingOnConnect)
  390. Receiver.StartSending();
  391. }
  392. }
  393. private static class StartSendingMsg
  394. {
  395. public static void Process(InputRemoting Receiver)
  396. {
  397. Receiver.StartSending();
  398. }
  399. }
  400. private static class StopSendingMsg
  401. {
  402. public static void Process(InputRemoting Receiver)
  403. {
  404. Receiver.StopSending();
  405. }
  406. }
  407. public void RemoveRemoteDevices(int participantId)
  408. {
  409. var senderIndex = FindOrCreateSenderRecord(participantId);
  410. // Remove devices added by remote.
  411. var devices = m_Senders[senderIndex].devices;
  412. if (devices != null)
  413. {
  414. foreach (var remoteDevice in devices)
  415. {
  416. var device = m_LocalManager.GetDeviceById(remoteDevice.localId);
  417. if (device != null)
  418. m_LocalManager.RemoveDevice(device);
  419. }
  420. }
  421. ////TODO: remove layouts added by remote
  422. ArrayHelpers.EraseAt(ref m_Senders, senderIndex);
  423. }
  424. private static class DisconnectMsg
  425. {
  426. public static void Process(InputRemoting Receiver, Message msg)
  427. {
  428. Receiver.RemoveRemoteDevices(msg.participantId);
  429. Receiver.StopSending();
  430. }
  431. }
  432. // Tell remote input system that there's a new layout.
  433. private static class NewLayoutMsg
  434. {
  435. [Serializable]
  436. public struct Data
  437. {
  438. public string name;
  439. public string layoutJson;
  440. public bool isOverride;
  441. }
  442. public static Message? Create(InputRemoting sender, string layoutName)
  443. {
  444. // Try to load the layout. Ignore the layout if it couldn't
  445. // be loaded.
  446. InputControlLayout layout;
  447. try
  448. {
  449. layout = sender.m_LocalManager.LoadLayout(new InternedString(layoutName));
  450. if (layout == null)
  451. {
  452. Debug.Log(string.Format(
  453. "Could not find layout '{0}' meant to be sent through remote connection; this should not happen",
  454. layoutName));
  455. return null;
  456. }
  457. }
  458. catch (Exception exception)
  459. {
  460. Debug.Log(string.Format(
  461. "Could not load layout '{0}'; not sending to remote listeners (exception: {1})", layoutName,
  462. exception));
  463. return null;
  464. }
  465. var data = new Data
  466. {
  467. name = layoutName,
  468. layoutJson = layout.ToJson(),
  469. isOverride = layout.isOverride
  470. };
  471. return new Message
  472. {
  473. type = MessageType.NewLayout,
  474. data = SerializeData(data)
  475. };
  476. }
  477. public static void Process(InputRemoting Receiver, Message msg)
  478. {
  479. var data = DeserializeData<Data>(msg.data);
  480. var senderIndex = Receiver.FindOrCreateSenderRecord(msg.participantId);
  481. var internedLayoutName = new InternedString(data.name);
  482. Receiver.m_LocalManager.RegisterControlLayout(data.layoutJson, data.name, data.isOverride);
  483. ArrayHelpers.Append(ref Receiver.m_Senders[senderIndex].layouts, internedLayoutName);
  484. }
  485. }
  486. private static class RemoveLayoutMsg
  487. {
  488. public static Message Create(string layoutName)
  489. {
  490. var bytes = Encoding.UTF8.GetBytes(layoutName);
  491. return new Message
  492. {
  493. type = MessageType.RemoveLayout,
  494. data = bytes
  495. };
  496. }
  497. public static void Process(InputRemoting Receiver, Message msg)
  498. {
  499. ////REVIEW: we probably don't want to do this blindly
  500. var layoutName = Encoding.UTF8.GetString(msg.data);
  501. Receiver.m_LocalManager.RemoveLayout(layoutName);
  502. }
  503. }
  504. // Tell remote input system that there's a new device.
  505. private static class NewDeviceMsg
  506. {
  507. [Serializable]
  508. public struct Data
  509. {
  510. public string name;
  511. public string layout;
  512. public int deviceId;
  513. public string[] usages;
  514. public InputDeviceDescription description;
  515. }
  516. public static Message Create(InputDevice device)
  517. {
  518. Debug.Assert(!device.remote, "Device being sent to remotes should be a local device, not a remote one");
  519. var data = new Data
  520. {
  521. name = device.name,
  522. layout = device.layout,
  523. deviceId = device.deviceId,
  524. description = device.description,
  525. usages = device.usages.Select(x => x.ToString()).ToArray()
  526. };
  527. var json = JsonUtility.ToJson(data);
  528. var bytes = Encoding.UTF8.GetBytes(json);
  529. return new Message
  530. {
  531. type = MessageType.NewDevice,
  532. data = bytes
  533. };
  534. }
  535. public static void Process(InputRemoting Receiver, Message msg)
  536. {
  537. var senderIndex = Receiver.FindOrCreateSenderRecord(msg.participantId);
  538. var data = DeserializeData<Data>(msg.data);
  539. // Make sure we haven't already seen the device.
  540. var devices = Receiver.m_Senders[senderIndex].devices;
  541. if (devices != null)
  542. {
  543. foreach (var entry in devices)
  544. if (entry.remoteId == data.deviceId)
  545. {
  546. Debug.LogError(string.Format(
  547. "Already received device with id {0} (layout '{1}', description '{3}) from remote {2}",
  548. data.deviceId,
  549. data.layout, msg.participantId, data.description));
  550. return;
  551. }
  552. }
  553. // Create device.
  554. InputDevice device;
  555. try
  556. {
  557. ////REVIEW: this gives remote devices names the same way that local devices receive them; should we make remote status visible in the name?
  558. device = Receiver.m_LocalManager.AddDevice(data.layout, data.name);
  559. }
  560. catch (Exception exception)
  561. {
  562. Debug.LogError(
  563. $"Could not create remote device '{data.description}' with layout '{data.layout}' locally (exception: {exception})");
  564. return;
  565. }
  566. // todo(kazuki)::Avoid to use reflection
  567. // device.m_ParticipantId = msg.participantId;
  568. device.SetParticipantId(msg.participantId);
  569. // todo(kazuki)::Avoid to use reflection
  570. // device.m_Description = data.description;
  571. // device.m_DeviceFlags |= InputDevice.DeviceFlags.Remote;
  572. device.SetDescription(data.description);
  573. var deviceFlagsRemote = 1 << 3;
  574. device.SetDeviceFlags(device.GetDeviceFlags() | deviceFlagsRemote);
  575. if(data.usages != null)
  576. foreach (var usage in data.usages)
  577. Receiver.m_LocalManager.AddDeviceUsage(device, usage);
  578. // Remember it.
  579. var record = new RemoteInputDevice
  580. {
  581. remoteId = data.deviceId,
  582. localId = device.deviceId,
  583. description = data.description
  584. };
  585. ArrayHelpers.Append(ref Receiver.m_Senders[senderIndex].devices, record);
  586. }
  587. }
  588. // Tell remote system there's new input events.
  589. private static class NewEventsMsg
  590. {
  591. // todo(kazuki):: not found DeviceResetEvent
  592. //public static unsafe Message CreateResetEvent(InputDevice device, bool isHardReset)
  593. //{
  594. // var resetEvent = DeviceResetEvent.Create(device.deviceId, isHardReset);
  595. // return Create((InputEvent*)UnsafeUtility.AddressOf(ref resetEvent), 1);
  596. //}
  597. public static unsafe Message CreateStateEvent(InputDevice device)
  598. {
  599. using (StateEvent.From(device, out var eventPtr))
  600. return Create(eventPtr.data, 1);
  601. }
  602. public static unsafe Message Create(InputEvent* events, int eventCount)
  603. {
  604. // Find total size of event buffer we need.
  605. var totalSize = 0u;
  606. var eventPtr = new InputEventPtr(events);
  607. for (var i = 0; i < eventCount; ++i, eventPtr = eventPtr.Next())
  608. {
  609. totalSize += eventPtr.sizeInBytes;
  610. }
  611. // Copy event data to buffer. Would be nice if we didn't have to do that
  612. // but unfortunately we need a byte[] and can't just pass the 'events' IntPtr
  613. // directly.
  614. var data = new byte[totalSize];
  615. fixed (byte* dataPtr = data)
  616. {
  617. UnsafeUtility.MemCpy(dataPtr, events, totalSize);
  618. }
  619. // Done.
  620. return new Message
  621. {
  622. type = MessageType.NewEvents,
  623. data = data
  624. };
  625. }
  626. public static unsafe void Process(InputRemoting Receiver, Message msg)
  627. {
  628. var manager = Receiver.m_LocalManager;
  629. fixed (byte* dataPtr = msg.data)
  630. {
  631. var dataEndPtr = new IntPtr(dataPtr + msg.data.Length);
  632. var eventCount = 0;
  633. var eventPtr = new InputEventPtr((InputEvent*)dataPtr);
  634. var senderIndex = Receiver.FindOrCreateSenderRecord(msg.participantId);
  635. while ((Int64)eventPtr.data < dataEndPtr.ToInt64())
  636. {
  637. // Patch up device ID to refer to local device and send event.
  638. var remoteDeviceId = eventPtr.deviceId;
  639. var localDeviceId = Receiver.FindLocalDeviceId(remoteDeviceId, senderIndex);
  640. eventPtr.deviceId = localDeviceId;
  641. if (localDeviceId != InputDevice.InvalidDeviceId)
  642. {
  643. ////TODO: add API to send events in bulk rather than one by one
  644. manager.QueueEvent(eventPtr);
  645. }
  646. ++eventCount;
  647. eventPtr = eventPtr.Next();
  648. }
  649. }
  650. }
  651. }
  652. private static class ChangeUsageMsg
  653. {
  654. [Serializable]
  655. public struct Data
  656. {
  657. public int deviceId;
  658. public string[] usages;
  659. }
  660. public static Message Create(InputDevice device)
  661. {
  662. var data = new Data
  663. {
  664. deviceId = device.deviceId,
  665. usages = device.usages.Select(x => x.ToString()).ToArray()
  666. };
  667. return new Message
  668. {
  669. type = MessageType.ChangeUsages,
  670. data = SerializeData(data)
  671. };
  672. }
  673. public static void Process(InputRemoting Receiver, Message msg)
  674. {
  675. var senderIndex = Receiver.FindOrCreateSenderRecord(msg.participantId);
  676. var data = DeserializeData<Data>(msg.data);
  677. var device = Receiver.TryGetDeviceByRemoteId(data.deviceId, senderIndex);
  678. if (device != null)
  679. {
  680. foreach (var deviceUsage in device.usages)
  681. {
  682. if (!data.usages.Contains(deviceUsage))
  683. Receiver.m_LocalManager.RemoveDeviceUsage(device, new InternedString(deviceUsage));
  684. }
  685. if (data.usages.Length == 1)
  686. Receiver.m_LocalManager.AddDeviceUsage(device, new InternedString(data.usages[0]));
  687. foreach (var dataUsage in data.usages)
  688. {
  689. var internedDataUsage = new InternedString(dataUsage);
  690. if (!device.usages.Contains(internedDataUsage))
  691. Receiver.m_LocalManager.AddDeviceUsage(device, new InternedString(dataUsage));
  692. }
  693. }
  694. }
  695. }
  696. private static class RemoveDeviceMsg
  697. {
  698. public static Message Create(InputDevice device)
  699. {
  700. return new Message
  701. {
  702. type = MessageType.RemoveDevice,
  703. data = BitConverter.GetBytes(device.deviceId)
  704. };
  705. }
  706. public static void Process(InputRemoting Receiver, Message msg)
  707. {
  708. var senderIndex = Receiver.FindOrCreateSenderRecord(msg.participantId);
  709. var remoteDeviceId = BitConverter.ToInt32(msg.data, 0);
  710. var device = Receiver.TryGetDeviceByRemoteId(remoteDeviceId, senderIndex);
  711. if (device != null)
  712. Receiver.m_LocalManager.RemoveDevice(device);
  713. }
  714. }
  715. private static byte[] SerializeData<TData>(TData data)
  716. {
  717. var json = JsonUtility.ToJson(data);
  718. return Encoding.UTF8.GetBytes(json);
  719. }
  720. private static TData DeserializeData<TData>(byte[] data)
  721. {
  722. var json = Encoding.UTF8.GetString(data);
  723. return JsonUtility.FromJson<TData>(json);
  724. }
  725. #if UNITY_EDITOR || DEVELOPMENT_BUILD
  726. // State we want to take across domain reloads. We can only take some of the
  727. // state across. Subscriptions will be lost and have to be manually restored.
  728. [Serializable]
  729. internal struct SerializedState
  730. {
  731. public int senderId;
  732. public RemoteSender[] senders;
  733. // We can't take these across domain reloads but we want to take them across
  734. // InputSystem.Save/Restore.
  735. [NonSerialized] public Subscriber[] subscribers;
  736. }
  737. internal SerializedState SaveState()
  738. {
  739. return new SerializedState
  740. {
  741. senders = m_Senders,
  742. subscribers = m_Subscribers
  743. };
  744. }
  745. internal void RestoreState(SerializedState state, IInputManager manager)
  746. {
  747. m_LocalManager = manager;
  748. m_Senders = state.senders;
  749. }
  750. #endif
  751. }
  752. }
  753. // #endif