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