PlayerInputEditor.cs 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570
  1. #if UNITY_EDITOR
  2. using System;
  3. using System.Collections.Generic;
  4. using System.IO;
  5. using System.Linq;
  6. using System.Text;
  7. using UnityEditor;
  8. using UnityEngine.InputSystem.Users;
  9. using UnityEngine.InputSystem.Utilities;
  10. #if UNITY_INPUT_SYSTEM_ENABLE_UI
  11. using UnityEngine.InputSystem.UI;
  12. using UnityEngine.InputSystem.UI.Editor;
  13. #endif
  14. ////TODO: detect if new input system isn't enabled and provide UI to enable it
  15. #pragma warning disable 0414
  16. namespace UnityEngine.InputSystem.Editor
  17. {
  18. /// <summary>
  19. /// A custom inspector for the <see cref="PlayerInput"/> component.
  20. /// </summary>
  21. [CustomEditor(typeof(PlayerInput))]
  22. internal class PlayerInputEditor : UnityEditor.Editor
  23. {
  24. public const string kDefaultInputActionsAssetPath =
  25. "Packages/com.unity.inputsystem/InputSystem/Plugins/PlayerInput/DefaultInputActions.inputactions";
  26. public void OnEnable()
  27. {
  28. InputActionImporter.onImport += Refresh;
  29. InputUser.onChange += OnUserChange;
  30. // Look up properties.
  31. m_ActionsProperty = serializedObject.FindProperty("m_Actions");
  32. m_DefaultControlSchemeProperty = serializedObject.FindProperty("m_DefaultControlScheme");
  33. m_NeverAutoSwitchControlSchemesProperty = serializedObject.FindProperty("m_NeverAutoSwitchControlSchemes");
  34. m_DefaultActionMapProperty = serializedObject.FindProperty("m_DefaultActionMap");
  35. m_NotificationBehaviorProperty = serializedObject.FindProperty("m_NotificationBehavior");
  36. m_CameraProperty = serializedObject.FindProperty("m_Camera");
  37. m_ActionEventsProperty = serializedObject.FindProperty("m_ActionEvents");
  38. m_DeviceLostEventProperty = serializedObject.FindProperty("m_DeviceLostEvent");
  39. m_DeviceRegainedEventProperty = serializedObject.FindProperty("m_DeviceRegainedEvent");
  40. m_ControlsChangedEventProperty = serializedObject.FindProperty("m_ControlsChangedEvent");
  41. #if UNITY_INPUT_SYSTEM_ENABLE_UI
  42. m_UIInputModuleProperty = serializedObject.FindProperty("m_UIInputModule");
  43. #endif
  44. }
  45. public void OnDestroy()
  46. {
  47. InputActionImporter.onImport -= Refresh;
  48. InputUser.onChange -= OnUserChange;
  49. }
  50. private void Refresh()
  51. {
  52. ////FIXME: doesn't seem like we're picking up the results of the latest import
  53. m_ActionAssetInitialized = false;
  54. Repaint();
  55. }
  56. private void OnUserChange(InputUser user, InputUserChange change, InputDevice device)
  57. {
  58. Repaint();
  59. }
  60. public override void OnInspectorGUI()
  61. {
  62. EditorGUI.BeginChangeCheck();
  63. // Action config section.
  64. EditorGUI.BeginChangeCheck();
  65. EditorGUILayout.PropertyField(m_ActionsProperty);
  66. if (EditorGUI.EndChangeCheck() || !m_ActionAssetInitialized)
  67. OnActionAssetChange();
  68. ++EditorGUI.indentLevel;
  69. if (m_ControlSchemeOptions != null && m_ControlSchemeOptions.Length > 1) // Don't show if <Any> is the only option.
  70. {
  71. // Default control scheme picker.
  72. var selected = EditorGUILayout.Popup(m_DefaultControlSchemeText, m_SelectedDefaultControlScheme,
  73. m_ControlSchemeOptions);
  74. if (selected != m_SelectedDefaultControlScheme)
  75. {
  76. if (selected == 0)
  77. {
  78. m_DefaultControlSchemeProperty.stringValue = null;
  79. }
  80. else
  81. {
  82. m_DefaultControlSchemeProperty.stringValue =
  83. m_ControlSchemeOptions[selected].text;
  84. }
  85. m_SelectedDefaultControlScheme = selected;
  86. }
  87. var neverAutoSwitchValueOld = m_NeverAutoSwitchControlSchemesProperty.boolValue;
  88. var neverAutoSwitchValueNew = !EditorGUILayout.Toggle(m_AutoSwitchText, !neverAutoSwitchValueOld);
  89. if (neverAutoSwitchValueOld != neverAutoSwitchValueNew)
  90. {
  91. m_NeverAutoSwitchControlSchemesProperty.boolValue = neverAutoSwitchValueNew;
  92. serializedObject.ApplyModifiedProperties();
  93. }
  94. }
  95. if (m_ActionMapOptions != null && m_ActionMapOptions.Length > 0)
  96. {
  97. // Default action map picker.
  98. var selected = EditorGUILayout.Popup(m_DefaultActionMapText, m_SelectedDefaultActionMap,
  99. m_ActionMapOptions);
  100. if (selected != m_SelectedDefaultActionMap)
  101. {
  102. if (selected == 0)
  103. {
  104. m_DefaultActionMapProperty.stringValue = null;
  105. }
  106. else
  107. {
  108. // Use ID rather than name.
  109. var asset = (InputActionAsset)m_ActionsProperty.objectReferenceValue;
  110. var actionMap = asset.FindActionMap(m_ActionMapOptions[selected].text);
  111. if (actionMap != null)
  112. m_DefaultActionMapProperty.stringValue = actionMap.id.ToString();
  113. }
  114. m_SelectedDefaultActionMap = selected;
  115. }
  116. }
  117. --EditorGUI.indentLevel;
  118. DoHelpCreateAssetUI();
  119. #if UNITY_INPUT_SYSTEM_ENABLE_UI
  120. // UI config section.
  121. if (m_UIPropertyText == null)
  122. m_UIPropertyText = EditorGUIUtility.TrTextContent("UI Input Module", m_UIInputModuleProperty.tooltip);
  123. EditorGUI.BeginChangeCheck();
  124. EditorGUILayout.PropertyField(m_UIInputModuleProperty, m_UIPropertyText);
  125. if (EditorGUI.EndChangeCheck())
  126. serializedObject.ApplyModifiedProperties();
  127. if (m_UIInputModuleProperty.objectReferenceValue != null)
  128. {
  129. var uiModule = m_UIInputModuleProperty.objectReferenceValue as InputSystemUIInputModule;
  130. if (m_ActionsProperty.objectReferenceValue != null && uiModule.actionsAsset != m_ActionsProperty.objectReferenceValue)
  131. {
  132. EditorGUILayout.HelpBox("The referenced InputSystemUIInputModule is configured using different input actions then this PlayerInput. They should match if you want to synchronize PlayerInput actions to the UI input.", MessageType.Warning);
  133. if (GUILayout.Button(m_FixInputModuleText))
  134. InputSystemUIInputModuleEditor.ReassignActions(uiModule, m_ActionsProperty.objectReferenceValue as InputActionAsset);
  135. }
  136. }
  137. #endif
  138. // Camera section.
  139. if (m_CameraPropertyText == null)
  140. m_CameraPropertyText = EditorGUIUtility.TrTextContent("Camera", m_CameraProperty.tooltip);
  141. EditorGUI.BeginChangeCheck();
  142. EditorGUILayout.PropertyField(m_CameraProperty, m_CameraPropertyText);
  143. if (EditorGUI.EndChangeCheck())
  144. serializedObject.ApplyModifiedProperties();
  145. // Notifications/event section.
  146. EditorGUI.BeginChangeCheck();
  147. EditorGUILayout.PropertyField(m_NotificationBehaviorProperty, m_NotificationBehaviorText);
  148. if (EditorGUI.EndChangeCheck() || !m_NotificationBehaviorInitialized)
  149. OnNotificationBehaviorChange();
  150. switch ((PlayerNotifications)m_NotificationBehaviorProperty.intValue)
  151. {
  152. case PlayerNotifications.SendMessages:
  153. case PlayerNotifications.BroadcastMessages:
  154. Debug.Assert(m_SendMessagesHelpText != null);
  155. EditorGUILayout.HelpBox(m_SendMessagesHelpText);
  156. break;
  157. case PlayerNotifications.InvokeUnityEvents:
  158. m_EventsGroupUnfolded = EditorGUILayout.Foldout(m_EventsGroupUnfolded, m_EventsGroupText, toggleOnLabelClick: true);
  159. if (m_EventsGroupUnfolded)
  160. {
  161. // Action events. Group by action map.
  162. if (m_ActionNames != null)
  163. {
  164. using (new EditorGUI.IndentLevelScope())
  165. {
  166. for (var n = 0; n < m_NumActionMaps; ++n)
  167. {
  168. m_ActionMapEventsUnfolded[n] = EditorGUILayout.Foldout(m_ActionMapEventsUnfolded[n],
  169. m_ActionMapNames[n], toggleOnLabelClick: true);
  170. using (new EditorGUI.IndentLevelScope())
  171. {
  172. if (m_ActionMapEventsUnfolded[n])
  173. {
  174. for (var i = 0; i < m_ActionNames.Length; ++i)
  175. {
  176. if (m_ActionMapIndices[i] != n)
  177. continue;
  178. EditorGUILayout.PropertyField(m_ActionEventsProperty.GetArrayElementAtIndex(i), m_ActionNames[i]);
  179. }
  180. }
  181. }
  182. }
  183. }
  184. }
  185. // Misc events.
  186. EditorGUILayout.PropertyField(m_DeviceLostEventProperty);
  187. EditorGUILayout.PropertyField(m_DeviceRegainedEventProperty);
  188. EditorGUILayout.PropertyField(m_ControlsChangedEventProperty);
  189. }
  190. break;
  191. }
  192. // Miscellaneous buttons.
  193. DoUtilityButtonsUI();
  194. if (EditorGUI.EndChangeCheck())
  195. serializedObject.ApplyModifiedProperties();
  196. // Debug UI.
  197. if (EditorApplication.isPlaying)
  198. DoDebugUI();
  199. }
  200. private void DoHelpCreateAssetUI()
  201. {
  202. if (m_ActionsProperty.objectReferenceValue != null)
  203. {
  204. // All good. We already have an asset.
  205. return;
  206. }
  207. EditorGUILayout.HelpBox("There are no input actions associated with this input component yet. Click the button below to create "
  208. + "a new set of input actions or drag an existing input actions asset into the field above.", MessageType.Info);
  209. EditorGUILayout.BeginHorizontal();
  210. EditorGUILayout.Space();
  211. if (GUILayout.Button(m_CreateActionsText, EditorStyles.miniButton, GUILayout.MaxWidth(120)))
  212. {
  213. // Request save file location.
  214. var defaultFileName = Application.productName;
  215. var fileName = EditorUtility.SaveFilePanel("Create Input Actions Asset", "Assets", defaultFileName,
  216. InputActionAsset.Extension);
  217. ////TODO: take current Supported Devices into account when creating this
  218. // Create and import asset and open editor.
  219. if (!string.IsNullOrEmpty(fileName))
  220. {
  221. if (!fileName.StartsWith(Application.dataPath))
  222. {
  223. Debug.LogError($"Path must be located in Assets/ folder (got: '{fileName}')");
  224. EditorGUILayout.EndHorizontal();
  225. return;
  226. }
  227. if (!fileName.EndsWith("." + InputActionAsset.Extension))
  228. fileName += "." + InputActionAsset.Extension;
  229. // Load default actions and update all GUIDs.
  230. var defaultActionsText = File.ReadAllText(kDefaultInputActionsAssetPath);
  231. var newActions = InputActionAsset.FromJson(defaultActionsText);
  232. foreach (var map in newActions.actionMaps)
  233. {
  234. map.m_Id = Guid.NewGuid().ToString();
  235. foreach (var action in map.actions)
  236. action.m_Id = Guid.NewGuid().ToString();
  237. }
  238. newActions.name = Path.GetFileNameWithoutExtension(fileName);
  239. var newActionsText = newActions.ToJson();
  240. // Write it out and tell the asset DB to pick it up.
  241. File.WriteAllText(fileName, newActionsText);
  242. AssetDatabase.Refresh();
  243. // Need to wait for import to happen. On next editor update, wire the asset
  244. // into our PlayerInput component and bring up the action editor.
  245. EditorApplication.delayCall +=
  246. () =>
  247. {
  248. var relativePath = "Assets/" + fileName.Substring(Application.dataPath.Length + 1);
  249. // Load imported object.
  250. var importedObject = AssetDatabase.LoadAssetAtPath<InputActionAsset>(relativePath);
  251. // Set it on the PlayerInput component.
  252. m_ActionsProperty.objectReferenceValue = importedObject;
  253. serializedObject.ApplyModifiedProperties();
  254. // Open the asset.
  255. AssetDatabase.OpenAsset(importedObject);
  256. };
  257. }
  258. }
  259. EditorGUILayout.EndHorizontal();
  260. EditorGUILayout.Separator();
  261. }
  262. private void DoUtilityButtonsUI()
  263. {
  264. EditorGUILayout.BeginHorizontal();
  265. if (GUILayout.Button(m_OpenSettingsText, EditorStyles.miniButton))
  266. InputSettingsProvider.Open();
  267. if (GUILayout.Button(m_OpenDebuggerText, EditorStyles.miniButton))
  268. InputDebuggerWindow.CreateOrShow();
  269. EditorGUILayout.EndHorizontal();
  270. }
  271. private void DoDebugUI()
  272. {
  273. var playerInput = (PlayerInput)target;
  274. if (!playerInput.user.valid)
  275. return;
  276. ////TODO: show actions when they happen
  277. var user = playerInput.user.index.ToString();
  278. var controlScheme = playerInput.user.controlScheme?.name;
  279. var devices = string.Join(", ", playerInput.user.pairedDevices);
  280. EditorGUILayout.Space();
  281. EditorGUILayout.LabelField(m_DebugText, EditorStyles.boldLabel);
  282. EditorGUI.BeginDisabledGroup(true);
  283. EditorGUILayout.LabelField("User", user);
  284. EditorGUILayout.LabelField("Control Scheme", controlScheme);
  285. EditorGUILayout.LabelField("Devices", devices);
  286. EditorGUI.EndDisabledGroup();
  287. }
  288. private void OnNotificationBehaviorChange()
  289. {
  290. Debug.Assert(m_ActionAssetInitialized);
  291. serializedObject.ApplyModifiedProperties();
  292. var notificationBehavior = (PlayerNotifications)m_NotificationBehaviorProperty.intValue;
  293. switch (notificationBehavior)
  294. {
  295. // Create text that lists all the messages sent by the component.
  296. case PlayerNotifications.BroadcastMessages:
  297. case PlayerNotifications.SendMessages:
  298. {
  299. var builder = new StringBuilder();
  300. builder.Append("Will ");
  301. if (notificationBehavior == PlayerNotifications.BroadcastMessages)
  302. builder.Append("BroadcastMessage()");
  303. else
  304. builder.Append("SendMessage()");
  305. builder.Append(" to GameObject: ");
  306. builder.Append(PlayerInput.DeviceLostMessage);
  307. builder.Append(", ");
  308. builder.Append(PlayerInput.DeviceRegainedMessage);
  309. builder.Append(", ");
  310. builder.Append(PlayerInput.ControlsChangedMessage);
  311. var playerInput = (PlayerInput)target;
  312. var asset = playerInput.m_Actions;
  313. if (asset != null)
  314. {
  315. foreach (var action in asset)
  316. {
  317. builder.Append(", On");
  318. builder.Append(CSharpCodeHelpers.MakeTypeName(action.name));
  319. }
  320. }
  321. m_SendMessagesHelpText = new GUIContent(builder.ToString());
  322. break;
  323. }
  324. case PlayerNotifications.InvokeUnityEvents:
  325. {
  326. var playerInput = (PlayerInput)target;
  327. if (playerInput.m_DeviceLostEvent == null)
  328. playerInput.m_DeviceLostEvent = new PlayerInput.DeviceLostEvent();
  329. if (playerInput.m_DeviceRegainedEvent == null)
  330. playerInput.m_DeviceRegainedEvent = new PlayerInput.DeviceRegainedEvent();
  331. if (playerInput.m_ControlsChangedEvent == null)
  332. playerInput.m_ControlsChangedEvent = new PlayerInput.ControlsChangedEvent();
  333. serializedObject.Update();
  334. // Force action refresh.
  335. m_ActionAssetInitialized = false;
  336. Refresh();
  337. break;
  338. }
  339. }
  340. m_NotificationBehaviorInitialized = true;
  341. }
  342. private void OnActionAssetChange()
  343. {
  344. serializedObject.ApplyModifiedProperties();
  345. m_ActionAssetInitialized = true;
  346. var playerInput = (PlayerInput)target;
  347. var asset = (InputActionAsset)m_ActionsProperty.objectReferenceValue;
  348. if (asset == null)
  349. {
  350. m_ControlSchemeOptions = null;
  351. m_ActionMapOptions = null;
  352. m_ActionNames = null;
  353. m_SelectedDefaultActionMap = -1;
  354. m_SelectedDefaultControlScheme = -1;
  355. return;
  356. }
  357. // If we're sending Unity events, read out the event list.
  358. if ((PlayerNotifications)m_NotificationBehaviorProperty.intValue ==
  359. PlayerNotifications.InvokeUnityEvents)
  360. {
  361. ////FIXME: this should preserve the same order that we have in the asset
  362. var newActionNames = new List<GUIContent>();
  363. var newActionEvents = new List<PlayerInput.ActionEvent>();
  364. var newActionMapIndices = new List<int>();
  365. m_NumActionMaps = 0;
  366. m_ActionMapNames = null;
  367. void AddEntry(InputAction action, PlayerInput.ActionEvent actionEvent)
  368. {
  369. newActionNames.Add(new GUIContent(action.name));
  370. newActionEvents.Add(actionEvent);
  371. var actionMapIndex = asset.actionMaps.IndexOfReference(action.actionMap);
  372. newActionMapIndices.Add(actionMapIndex);
  373. if (actionMapIndex >= m_NumActionMaps)
  374. m_NumActionMaps = actionMapIndex + 1;
  375. ArrayHelpers.PutAtIfNotSet(ref m_ActionMapNames, actionMapIndex,
  376. () => new GUIContent(action.actionMap.name));
  377. }
  378. ////REVIEW: this is destructive; we may be losing connections here that the user has set up
  379. //// if the action goes missing
  380. // Bring over any action events that we already have and that are still in the asset.
  381. var oldActionEvents = playerInput.m_ActionEvents;
  382. if (oldActionEvents != null)
  383. {
  384. foreach (var entry in oldActionEvents)
  385. {
  386. var guid = entry.actionId;
  387. var action = asset.FindAction(guid);
  388. if (action != null)
  389. AddEntry(action, entry);
  390. }
  391. }
  392. // Add any new actions.
  393. foreach (var action in asset)
  394. {
  395. // Skip if it was already in there.
  396. if (oldActionEvents != null && oldActionEvents.Any(x => x.actionId == action.id.ToString()))
  397. continue;
  398. ////FIXME: adds bindings to the name
  399. AddEntry(action, new PlayerInput.ActionEvent(action.id, action.ToString()));
  400. }
  401. m_ActionNames = newActionNames.ToArray();
  402. m_ActionMapIndices = newActionMapIndices.ToArray();
  403. Array.Resize(ref m_ActionMapEventsUnfolded, m_NumActionMaps);
  404. playerInput.m_ActionEvents = newActionEvents.ToArray();
  405. }
  406. // Read out control schemes.
  407. var selectedDefaultControlScheme = playerInput.defaultControlScheme;
  408. m_SelectedDefaultControlScheme = 0;
  409. var controlSchemes = asset.controlSchemes;
  410. m_ControlSchemeOptions = new GUIContent[controlSchemes.Count + 1];
  411. m_ControlSchemeOptions[0] = new GUIContent(EditorGUIUtility.TrTextContent("<Any>"));
  412. ////TODO: sort alphabetically
  413. for (var i = 0; i < controlSchemes.Count; ++i)
  414. {
  415. var name = controlSchemes[i].name;
  416. m_ControlSchemeOptions[i + 1] = new GUIContent(name);
  417. if (selectedDefaultControlScheme != null && string.Compare(name, selectedDefaultControlScheme,
  418. StringComparison.InvariantCultureIgnoreCase) == 0)
  419. m_SelectedDefaultControlScheme = i + 1;
  420. }
  421. if (m_SelectedDefaultControlScheme <= 0)
  422. playerInput.defaultControlScheme = null;
  423. // Read out action maps.
  424. var selectedDefaultActionMap = !string.IsNullOrEmpty(playerInput.defaultActionMap)
  425. ? asset.FindActionMap(playerInput.defaultActionMap)
  426. : null;
  427. m_SelectedDefaultActionMap = asset.actionMaps.Count > 0 ? 1 : 0;
  428. var actionMaps = asset.actionMaps;
  429. m_ActionMapOptions = new GUIContent[actionMaps.Count + 1];
  430. m_ActionMapOptions[0] = new GUIContent(EditorGUIUtility.TrTextContent("<None>"));
  431. ////TODO: sort alphabetically
  432. for (var i = 0; i < actionMaps.Count; ++i)
  433. {
  434. var actionMap = actionMaps[i];
  435. m_ActionMapOptions[i + 1] = new GUIContent(actionMap.name);
  436. if (selectedDefaultActionMap != null && actionMap == selectedDefaultActionMap)
  437. m_SelectedDefaultActionMap = i + 1;
  438. }
  439. if (m_SelectedDefaultActionMap <= 0)
  440. playerInput.defaultActionMap = null;
  441. else
  442. playerInput.defaultActionMap = m_ActionMapOptions[m_SelectedDefaultActionMap].text;
  443. serializedObject.Update();
  444. }
  445. [SerializeField] private bool m_EventsGroupUnfolded;
  446. [SerializeField] private bool[] m_ActionMapEventsUnfolded;
  447. [NonSerialized] private readonly GUIContent m_CreateActionsText = EditorGUIUtility.TrTextContent("Create Actions...");
  448. [NonSerialized] private readonly GUIContent m_FixInputModuleText = EditorGUIUtility.TrTextContent("Fix UI Input Module");
  449. [NonSerialized] private readonly GUIContent m_OpenSettingsText = EditorGUIUtility.TrTextContent("Open Input Settings");
  450. [NonSerialized] private readonly GUIContent m_OpenDebuggerText = EditorGUIUtility.TrTextContent("Open Input Debugger");
  451. [NonSerialized] private readonly GUIContent m_EventsGroupText =
  452. EditorGUIUtility.TrTextContent("Events", "UnityEvents triggered by the PlayerInput component");
  453. [NonSerialized] private readonly GUIContent m_NotificationBehaviorText =
  454. EditorGUIUtility.TrTextContent("Behavior",
  455. "Determine how notifications should be sent when an input-related event associated with the player happens.");
  456. [NonSerialized] private readonly GUIContent m_DefaultControlSchemeText =
  457. EditorGUIUtility.TrTextContent("Default Scheme", "Which control scheme to try by default. If not set, PlayerInput "
  458. + "will simply go through all control schemes in the action asset and try one after the other. If set, PlayerInput will try "
  459. + "the given scheme first but if using that fails (e.g. when not required devices are missing) will fall back to trying the other "
  460. + "control schemes in order.");
  461. [NonSerialized] private readonly GUIContent m_DefaultActionMapText =
  462. EditorGUIUtility.TrTextContent("Default Map", "Action map to enable by default. If not set, no actions will be enabled by default.");
  463. [NonSerialized] private readonly GUIContent m_AutoSwitchText =
  464. EditorGUIUtility.TrTextContent("Auto-Switch",
  465. "By default, when there is only a single PlayerInput, the player "
  466. + "is allowed to freely switch between control schemes simply by starting to use a different device. By toggling this property off, this "
  467. + "behavior is disabled and even with a single player, the player will stay locked onto the explicitly selected control scheme. Note "
  468. + "that you can still change control schemes explicitly through the PlayerInput API.\n\nWhen there are multiple PlayerInputs in the game, auto-switching is disabled automatically regardless of the value of this property.");
  469. [NonSerialized] private readonly GUIContent m_DebugText = EditorGUIUtility.TrTextContent("Debug");
  470. [NonSerialized] private GUIContent m_UIPropertyText;
  471. [NonSerialized] private GUIContent m_CameraPropertyText;
  472. [NonSerialized] private GUIContent m_SendMessagesHelpText;
  473. [NonSerialized] private GUIContent[] m_ActionNames;
  474. [NonSerialized] private GUIContent[] m_ActionMapNames;
  475. [NonSerialized] private int[] m_ActionMapIndices;
  476. [NonSerialized] private int m_NumActionMaps;
  477. [NonSerialized] private int m_SelectedDefaultControlScheme;
  478. [NonSerialized] private GUIContent[] m_ControlSchemeOptions;
  479. [NonSerialized] private int m_SelectedDefaultActionMap;
  480. [NonSerialized] private GUIContent[] m_ActionMapOptions;
  481. [NonSerialized] private SerializedProperty m_ActionsProperty;
  482. [NonSerialized] private SerializedProperty m_DefaultControlSchemeProperty;
  483. [NonSerialized] private SerializedProperty m_DefaultActionMapProperty;
  484. [NonSerialized] private SerializedProperty m_NeverAutoSwitchControlSchemesProperty;
  485. [NonSerialized] private SerializedProperty m_NotificationBehaviorProperty;
  486. #if UNITY_INPUT_SYSTEM_ENABLE_UI
  487. [NonSerialized] private SerializedProperty m_UIInputModuleProperty;
  488. #endif
  489. [NonSerialized] private SerializedProperty m_ActionEventsProperty;
  490. [NonSerialized] private SerializedProperty m_CameraProperty;
  491. [NonSerialized] private SerializedProperty m_DeviceLostEventProperty;
  492. [NonSerialized] private SerializedProperty m_DeviceRegainedEventProperty;
  493. [NonSerialized] private SerializedProperty m_ControlsChangedEventProperty;
  494. [NonSerialized] private bool m_NotificationBehaviorInitialized;
  495. [NonSerialized] private bool m_ActionAssetInitialized;
  496. }
  497. }
  498. #endif // UNITY_EDITOR