RebindActionUIEditor.cs 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. #if UNITY_EDITOR
  2. using System.Linq;
  3. using UnityEditor;
  4. ////TODO: support multi-object editing
  5. namespace UnityEngine.InputSystem.Samples.RebindUI
  6. {
  7. /// <summary>
  8. /// A custom inspector for <see cref="RebindActionUI"/> which provides a more convenient way for
  9. /// picking the binding which to rebind.
  10. /// </summary>
  11. [CustomEditor(typeof(RebindActionUI))]
  12. public class RebindActionUIEditor : UnityEditor.Editor
  13. {
  14. protected void OnEnable()
  15. {
  16. m_ActionProperty = serializedObject.FindProperty("m_Action");
  17. m_BindingIdProperty = serializedObject.FindProperty("m_BindingId");
  18. m_ActionLabelProperty = serializedObject.FindProperty("m_ActionLabel");
  19. m_BindingTextProperty = serializedObject.FindProperty("m_BindingText");
  20. m_RebindOverlayProperty = serializedObject.FindProperty("m_RebindOverlay");
  21. m_RebindTextProperty = serializedObject.FindProperty("m_RebindText");
  22. m_UpdateBindingUIEventProperty = serializedObject.FindProperty("m_UpdateBindingUIEvent");
  23. m_RebindStartEventProperty = serializedObject.FindProperty("m_RebindStartEvent");
  24. m_RebindStopEventProperty = serializedObject.FindProperty("m_RebindStopEvent");
  25. m_DisplayStringOptionsProperty = serializedObject.FindProperty("m_DisplayStringOptions");
  26. RefreshBindingOptions();
  27. }
  28. public override void OnInspectorGUI()
  29. {
  30. EditorGUI.BeginChangeCheck();
  31. // Binding section.
  32. EditorGUILayout.LabelField(m_BindingLabel, Styles.boldLabel);
  33. using (new EditorGUI.IndentLevelScope())
  34. {
  35. EditorGUILayout.PropertyField(m_ActionProperty);
  36. var newSelectedBinding = EditorGUILayout.Popup(m_BindingLabel, m_SelectedBindingOption, m_BindingOptions);
  37. if (newSelectedBinding != m_SelectedBindingOption)
  38. {
  39. var bindingId = m_BindingOptionValues[newSelectedBinding];
  40. m_BindingIdProperty.stringValue = bindingId;
  41. m_SelectedBindingOption = newSelectedBinding;
  42. }
  43. var optionsOld = (InputBinding.DisplayStringOptions)m_DisplayStringOptionsProperty.intValue;
  44. var optionsNew = (InputBinding.DisplayStringOptions)EditorGUILayout.EnumFlagsField(m_DisplayOptionsLabel, optionsOld);
  45. if (optionsOld != optionsNew)
  46. m_DisplayStringOptionsProperty.intValue = (int)optionsNew;
  47. }
  48. // UI section.
  49. EditorGUILayout.Space();
  50. EditorGUILayout.LabelField(m_UILabel, Styles.boldLabel);
  51. using (new EditorGUI.IndentLevelScope())
  52. {
  53. EditorGUILayout.PropertyField(m_ActionLabelProperty);
  54. EditorGUILayout.PropertyField(m_BindingTextProperty);
  55. EditorGUILayout.PropertyField(m_RebindOverlayProperty);
  56. EditorGUILayout.PropertyField(m_RebindTextProperty);
  57. }
  58. // Events section.
  59. EditorGUILayout.Space();
  60. EditorGUILayout.LabelField(m_EventsLabel, Styles.boldLabel);
  61. using (new EditorGUI.IndentLevelScope())
  62. {
  63. EditorGUILayout.PropertyField(m_RebindStartEventProperty);
  64. EditorGUILayout.PropertyField(m_RebindStopEventProperty);
  65. EditorGUILayout.PropertyField(m_UpdateBindingUIEventProperty);
  66. }
  67. if (EditorGUI.EndChangeCheck())
  68. {
  69. serializedObject.ApplyModifiedProperties();
  70. RefreshBindingOptions();
  71. }
  72. }
  73. protected void RefreshBindingOptions()
  74. {
  75. var actionReference = (InputActionReference)m_ActionProperty.objectReferenceValue;
  76. var action = actionReference?.action;
  77. if (action == null)
  78. {
  79. m_BindingOptions = new GUIContent[0];
  80. m_BindingOptionValues = new string[0];
  81. m_SelectedBindingOption = -1;
  82. return;
  83. }
  84. var bindings = action.bindings;
  85. var bindingCount = bindings.Count;
  86. m_BindingOptions = new GUIContent[bindingCount];
  87. m_BindingOptionValues = new string[bindingCount];
  88. m_SelectedBindingOption = -1;
  89. var currentBindingId = m_BindingIdProperty.stringValue;
  90. for (var i = 0; i < bindingCount; ++i)
  91. {
  92. var binding = bindings[i];
  93. var bindingId = binding.id.ToString();
  94. var haveBindingGroups = !string.IsNullOrEmpty(binding.groups);
  95. // If we don't have a binding groups (control schemes), show the device that if there are, for example,
  96. // there are two bindings with the display string "A", the user can see that one is for the keyboard
  97. // and the other for the gamepad.
  98. var displayOptions =
  99. InputBinding.DisplayStringOptions.DontUseShortDisplayNames | InputBinding.DisplayStringOptions.IgnoreBindingOverrides;
  100. if (!haveBindingGroups)
  101. displayOptions |= InputBinding.DisplayStringOptions.DontOmitDevice;
  102. // Create display string.
  103. var displayString = action.GetBindingDisplayString(i, displayOptions);
  104. // If binding is part of a composite, include the part name.
  105. if (binding.isPartOfComposite)
  106. displayString = $"{ObjectNames.NicifyVariableName(binding.name)}: {displayString}";
  107. // Some composites use '/' as a separator. When used in popup, this will lead to to submenus. Prevent
  108. // by instead using a backlash.
  109. displayString = displayString.Replace('/', '\\');
  110. // If the binding is part of control schemes, mention them.
  111. if (haveBindingGroups)
  112. {
  113. var asset = action.actionMap?.asset;
  114. if (asset != null)
  115. {
  116. var controlSchemes = string.Join(", ",
  117. binding.groups.Split(InputBinding.Separator)
  118. .Select(x => asset.controlSchemes.FirstOrDefault(c => c.bindingGroup == x).name));
  119. displayString = $"{displayString} ({controlSchemes})";
  120. }
  121. }
  122. m_BindingOptions[i] = new GUIContent(displayString);
  123. m_BindingOptionValues[i] = bindingId;
  124. if (currentBindingId == bindingId)
  125. m_SelectedBindingOption = i;
  126. }
  127. }
  128. private SerializedProperty m_ActionProperty;
  129. private SerializedProperty m_BindingIdProperty;
  130. private SerializedProperty m_ActionLabelProperty;
  131. private SerializedProperty m_BindingTextProperty;
  132. private SerializedProperty m_RebindOverlayProperty;
  133. private SerializedProperty m_RebindTextProperty;
  134. private SerializedProperty m_RebindStartEventProperty;
  135. private SerializedProperty m_RebindStopEventProperty;
  136. private SerializedProperty m_UpdateBindingUIEventProperty;
  137. private SerializedProperty m_DisplayStringOptionsProperty;
  138. private GUIContent m_BindingLabel = new GUIContent("Binding");
  139. private GUIContent m_DisplayOptionsLabel = new GUIContent("Display Options");
  140. private GUIContent m_UILabel = new GUIContent("UI");
  141. private GUIContent m_EventsLabel = new GUIContent("Events");
  142. private GUIContent[] m_BindingOptions;
  143. private string[] m_BindingOptionValues;
  144. private int m_SelectedBindingOption;
  145. private static class Styles
  146. {
  147. public static GUIStyle boldLabel = new GUIStyle("MiniBoldLabel");
  148. }
  149. }
  150. }
  151. #endif