No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

PlayerInputEditor.cs 28KB

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