InputReceiver.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439
  1. using System;
  2. using System.Linq;
  3. using Unity.WebRTC;
  4. using UnityEngine;
  5. using UnityEngine.InputSystem;
  6. using UnityEngine.InputSystem.Utilities;
  7. using UnityEngine.InputSystem.Users;
  8. using Unity.RenderStreaming.InputSystem;
  9. using Inputs = UnityEngine.InputSystem.InputSystem;
  10. using InputRemoting = Unity.RenderStreaming.InputSystem.InputRemoting;
  11. namespace Unity.RenderStreaming
  12. {
  13. /// <summary>
  14. /// Represents a separate player in the game complete with a set of actions exclusive
  15. /// to the player and a set of paired device.
  16. /// It is the simple version of UnityEngine.InputSystem.PlayerInput that removing dependency of InputControlScheme.
  17. /// </summary>
  18. [AddComponentMenu("Render Streaming/Input Receiver")]
  19. public class InputReceiver : InputChannelReceiverBase
  20. {
  21. /// <summary>
  22. ///
  23. /// </summary>
  24. public override event Action<InputDevice, InputDeviceChange> onDeviceChange;
  25. /// <summary>
  26. ///
  27. /// </summary>
  28. public InputActionAsset actions
  29. {
  30. get
  31. {
  32. if (!m_ActionsInitialized && gameObject.activeSelf)
  33. InitializeActions();
  34. return m_Actions;
  35. }
  36. set
  37. {
  38. if (m_Actions == value)
  39. return;
  40. // Make sure that if we already have actions, they get disabled.
  41. if (m_Actions != null)
  42. {
  43. m_Actions.Disable();
  44. if (m_Enabled)
  45. UninitializeActions();
  46. }
  47. m_Actions = value;
  48. if (m_Enabled)
  49. {
  50. //ClearCaches();
  51. AssignUserAndDevices();
  52. InitializeActions();
  53. if (m_InputActive)
  54. ActivateInput();
  55. }
  56. }
  57. }
  58. /// <summary>
  59. ///
  60. /// </summary>
  61. public bool inputIsActive => m_InputActive;
  62. /// <summary>
  63. ///
  64. /// </summary>
  65. public InputUser user => m_InputUser;
  66. /// <summary>
  67. ///
  68. /// </summary>
  69. public ReadOnlyArray<InputDevice> devices => m_InputUser.pairedDevices;
  70. /// <summary>
  71. ///
  72. /// </summary>
  73. public InputActionMap currentActionMap
  74. {
  75. get => m_CurrentActionMap;
  76. set
  77. {
  78. m_CurrentActionMap?.Disable();
  79. m_CurrentActionMap = value;
  80. m_CurrentActionMap?.Enable();
  81. }
  82. }
  83. /// <summary>
  84. ///
  85. /// </summary>
  86. public string defaultActionMap
  87. {
  88. get => m_DefaultActionMap;
  89. set => m_DefaultActionMap = value;
  90. }
  91. /// <summary>
  92. ///
  93. /// </summary>
  94. public ReadOnlyArray<PlayerInput.ActionEvent> actionEvents
  95. {
  96. get => m_ActionEvents;
  97. set
  98. {
  99. if (m_Enabled)
  100. UninitializeActions();
  101. m_ActionEvents = value.ToArray();
  102. if (m_Enabled)
  103. InitializeActions();
  104. }
  105. }
  106. /// <summary>
  107. ///
  108. /// </summary>
  109. protected virtual void OnEnable()
  110. {
  111. m_Enabled = true;
  112. onDeviceChange += OnDeviceChange;
  113. //AssignPlayerIndex();
  114. InitializeActions();
  115. AssignUserAndDevices();
  116. ActivateInput();
  117. }
  118. /// <summary>
  119. ///
  120. /// </summary>
  121. protected virtual void OnDisable()
  122. {
  123. m_Enabled = false;
  124. onDeviceChange -= OnDeviceChange;
  125. DeactivateInput();
  126. UnassignUserAndDevices();
  127. UninitializeActions();
  128. }
  129. /// <summary>
  130. ///
  131. /// </summary>
  132. public void ActivateInput()
  133. {
  134. m_InputActive = true;
  135. // If we have no current action map but there's a default
  136. // action map, make it current.
  137. if (m_CurrentActionMap == null && m_Actions != null && !string.IsNullOrEmpty(m_DefaultActionMap))
  138. SwitchCurrentActionMap(m_DefaultActionMap);
  139. else
  140. m_CurrentActionMap?.Enable();
  141. }
  142. /// <summary>
  143. ///
  144. /// </summary>
  145. public void DeactivateInput()
  146. {
  147. m_CurrentActionMap?.Disable();
  148. m_InputActive = false;
  149. }
  150. /// <summary>
  151. ///
  152. /// </summary>
  153. /// <param name="mapNameOrId"></param>
  154. public void SwitchCurrentActionMap(string mapNameOrId)
  155. {
  156. // Must be enabled.
  157. if (!m_Enabled)
  158. {
  159. Debug.LogError($"Cannot switch to actions '{mapNameOrId}'; input is not enabled", this);
  160. return;
  161. }
  162. // Must have actions.
  163. if (m_Actions == null)
  164. {
  165. Debug.LogError($"Cannot switch to actions '{mapNameOrId}'; no actions set on PlayerInput", this);
  166. return;
  167. }
  168. // Must have map.
  169. var actionMap = m_Actions.FindActionMap(mapNameOrId);
  170. if (actionMap == null)
  171. {
  172. Debug.LogError($"Cannot find action map '{mapNameOrId}' in actions '{m_Actions}'", this);
  173. return;
  174. }
  175. currentActionMap = actionMap;
  176. }
  177. /// <summary>
  178. ///
  179. /// </summary>
  180. /// <param name="device"></param>
  181. public void PerformPairingWithDevice(InputDevice device)
  182. {
  183. m_InputUser = InputUser.PerformPairingWithDevice(device, m_InputUser);
  184. }
  185. /// <summary>
  186. ///
  187. /// </summary>
  188. public void PerformPairingWithAllLocalDevices()
  189. {
  190. foreach (var device in Inputs.devices.Where(_ => !_.remote))
  191. {
  192. PerformPairingWithDevice(device);
  193. }
  194. }
  195. /// <summary>
  196. ///
  197. /// </summary>
  198. /// <param name="device"></param>
  199. public void UnpairDevices(InputDevice device)
  200. {
  201. if (!m_InputUser.valid)
  202. return;
  203. m_InputUser.UnpairDevice(device);
  204. }
  205. /// <summary>
  206. ///
  207. /// </summary>
  208. /// <param name="track"></param>
  209. public override void SetChannel(string connectionId, RTCDataChannel channel)
  210. {
  211. if (channel == null)
  212. {
  213. Dispose();
  214. }
  215. else
  216. {
  217. receiver = new Receiver(channel);
  218. receiver.onDeviceChange += onDeviceChange;
  219. receiverInput = new InputRemoting(receiver);
  220. subscriberDisposer = receiverInput.Subscribe(receiverInput);
  221. receiverInput.StartSending();
  222. }
  223. base.SetChannel(connectionId, channel);
  224. }
  225. /// <summary>
  226. ///
  227. /// </summary>
  228. /// <param name="size">Texture Size.</param>
  229. /// <param name="region">Region of the texture in world coordinate system.</param>
  230. public void CalculateInputRegion(Vector2Int size, Rect region)
  231. {
  232. receiver.CalculateInputRegion(new Rect(Vector2.zero, size), region);
  233. }
  234. /// <summary>
  235. ///
  236. /// </summary>
  237. /// <param name="enabled"></param>
  238. public void SetEnableInputPositionCorrection(bool enabled)
  239. {
  240. receiver.EnableInputPositionCorrection = enabled;
  241. }
  242. /// <summary>
  243. ///
  244. /// </summary>
  245. protected virtual void OnDestroy()
  246. {
  247. Dispose();
  248. }
  249. protected virtual void Dispose()
  250. {
  251. receiverInput?.StopSending();
  252. subscriberDisposer?.Dispose();
  253. receiver?.Dispose();
  254. receiver = null;
  255. }
  256. [Tooltip("Input actions associated with the player.")]
  257. [SerializeField] internal InputActionAsset m_Actions;
  258. [SerializeField] internal PlayerInput.ActionEvent[] m_ActionEvents;
  259. [SerializeField] internal string m_DefaultActionMap;
  260. [NonSerialized] internal InputActionMap m_CurrentActionMap;
  261. [NonSerialized] private bool m_InputActive;
  262. [NonSerialized] private bool m_Enabled;
  263. [NonSerialized] private bool m_ActionsInitialized;
  264. [NonSerialized] private InputUser m_InputUser;
  265. [NonSerialized] private Receiver receiver;
  266. [NonSerialized] private InputRemoting receiverInput;
  267. [NonSerialized] private IDisposable subscriberDisposer;
  268. private void AssignUserAndDevices()
  269. {
  270. // If we already have a user at this point, clear out all its paired devices
  271. // to start the pairing process from scratch.
  272. if (m_InputUser.valid)
  273. m_InputUser.UnpairDevices();
  274. // All our input goes through actions so there's no point setting
  275. // anything up if we have none.
  276. if (m_Actions == null)
  277. {
  278. // Make sure user is invalid.
  279. m_InputUser = new InputUser();
  280. return;
  281. }
  282. m_InputUser = InputUser.CreateUserWithoutPairedDevices();
  283. // If we don't have a valid user at this point, we don't have any paired devices.
  284. if (m_InputUser.valid)
  285. m_InputUser.AssociateActionsWithUser(actions);
  286. }
  287. private void UnassignUserAndDevices()
  288. {
  289. m_InputUser.UnpairDevicesAndRemoveUser();
  290. }
  291. private void InitializeActions()
  292. {
  293. if (m_ActionsInitialized)
  294. return;
  295. if (m_Actions == null)
  296. return;
  297. var oldActions = m_Actions;
  298. m_Actions = Instantiate(m_Actions);
  299. for (var actionMap = 0; actionMap < oldActions.actionMaps.Count; actionMap++)
  300. {
  301. for (var binding = 0; binding < oldActions.actionMaps[actionMap].bindings.Count; binding++)
  302. m_Actions.actionMaps[actionMap].ApplyBindingOverride(binding, oldActions.actionMaps[actionMap].bindings[binding]);
  303. }
  304. // Hook up all action events.
  305. if (m_ActionEvents != null)
  306. {
  307. foreach (var actionEvent in m_ActionEvents)
  308. {
  309. var id = actionEvent.actionId;
  310. if (string.IsNullOrEmpty(id))
  311. continue;
  312. // Find action for event.
  313. var action = m_Actions.FindAction(id);
  314. if (action != null)
  315. {
  316. ////REVIEW: really wish we had a single callback
  317. action.performed += actionEvent.Invoke;
  318. action.canceled += actionEvent.Invoke;
  319. action.started += actionEvent.Invoke;
  320. }
  321. else
  322. {
  323. // Cannot find action. Log error.
  324. if (!string.IsNullOrEmpty(actionEvent.actionName))
  325. {
  326. // We have an action name. Show in message.
  327. Debug.LogError(
  328. $"Cannot find action '{actionEvent.actionName}' with ID '{actionEvent.actionId}' in '{m_Actions}",
  329. this);
  330. }
  331. else
  332. {
  333. // We have no action name. Best we have is ID.
  334. Debug.LogError(
  335. $"Cannot find action with ID '{actionEvent.actionId}' in '{m_Actions}",
  336. this);
  337. }
  338. }
  339. }
  340. }
  341. m_ActionsInitialized = true;
  342. }
  343. private void UninitializeActions()
  344. {
  345. if (!m_ActionsInitialized)
  346. return;
  347. if (m_Actions == null)
  348. return;
  349. //UninstallOnActionTriggeredHook();
  350. if (m_ActionEvents != null)
  351. {
  352. foreach (var actionEvent in m_ActionEvents)
  353. {
  354. var id = actionEvent.actionId;
  355. if (string.IsNullOrEmpty(id))
  356. continue;
  357. // Find action for event.
  358. var action = m_Actions.FindAction(id);
  359. if (action != null)
  360. {
  361. ////REVIEW: really wish we had a single callback
  362. action.performed -= actionEvent.Invoke;
  363. action.canceled -= actionEvent.Invoke;
  364. action.started -= actionEvent.Invoke;
  365. }
  366. }
  367. }
  368. m_CurrentActionMap = null;
  369. m_ActionsInitialized = false;
  370. }
  371. protected virtual void OnDeviceChange(InputDevice device, InputDeviceChange change)
  372. {
  373. switch (change)
  374. {
  375. case InputDeviceChange.Added:
  376. PerformPairingWithDevice(device);
  377. return;
  378. case InputDeviceChange.Removed:
  379. UnpairDevices(device);
  380. return;
  381. }
  382. }
  383. }
  384. }