void DrawActionGUI() { EditorGUI.BeginChangeCheck(); string name = EditorGUILayout.TextField("Name", selectedAction.controlData.name); if (EditorGUI.EndChangeCheck()) { InputControlData data = selectedAction.controlData; data.name = name; selectedAction.controlData = data; selectedAction.name = name; RefreshPropertyNames(); } EditorGUI.BeginChangeCheck(); Rect rect = EditorGUILayout.GetControlRect(); Type type = TypeGUI.TypeField(rect, new GUIContent("Control Type"), typeof(InputControl), selectedAction.controlData.controlType); if (EditorGUI.EndChangeCheck()) { InputControlData data = selectedAction.controlData; data.controlType = type; selectedAction.controlData = data; } EditorGUILayout.Space(); string[] sourceControlNames = GetSourceControlNames(selectedAction.controlData.controlType); if (sourceControlNames != null) { DrawCompositeControl(selectedAction, sourceControlNames); } else { if (selectedScheme >= 0 && selectedScheme < m_ActionMapEditCopy.controlSchemes.Count) { int actionIndex = m_ActionMapEditCopy.actions.IndexOf(selectedAction); DrawBinding(m_ActionMapEditCopy.controlSchemes[selectedScheme].bindings[actionIndex]); } } }
public void OnGUI(Rect rect, GUIContent label, Type baseType = null, SerializedProperty prop = null) { if (prop != null) { label = EditorGUI.BeginProperty(rect, label, prop); } if (baseType == null) { baseType = typeof(InputDevice); } List <string> tagNames = null; Vector2 tagMaxSize = Vector2.zero; if (type.value != null) { tagNames = InputDeviceUtility.GetDeviceTags(type.value); if (tagNames != null) { GUIContent content = new GUIContent(); for (var j = 0; j < tagNames.Count; j++) { content.text = tagNames[j]; Vector2 size = EditorStyles.popup.CalcSize(content); tagMaxSize = Vector2.Max(size, tagMaxSize); } } } rect.width -= tagMaxSize.x; // Adjust width to leave room for tag EditorGUI.BeginChangeCheck(); Type t = TypeGUI.TypeField(rect, label, baseType, type); if (EditorGUI.EndChangeCheck()) { if (prop != null) { Undo.RecordObjects(prop.serializedObject.targetObjects, "Input Device"); } type = t; if (prop != null) { // Flushing seems necessaary to have prefab property override status change without lag. Undo.FlushUndoRecordObjects(); prop.serializedObject.SetIsDifferentCacheDirty(); } } if (tagNames != null) { int oldIndent = EditorGUI.indentLevel; EditorGUI.indentLevel = 0; EditorGUI.BeginChangeCheck(); // We want to have the ability to unset a tag after specifying one, so add an "Any" option var popupTags = new string[tagNames.Count + 1]; popupTags[0] = "Any"; tagNames.CopyTo(popupTags, 1); int newTagIndex = tagIndex + 1; rect.x += rect.width; rect.width = tagMaxSize.x; newTagIndex = EditorGUI.Popup( rect, newTagIndex, popupTags); if (EditorGUI.EndChangeCheck()) { if (prop != null) { Undo.RecordObjects(prop.serializedObject.targetObjects, "Control"); } tagIndex = newTagIndex - 1; if (prop != null) { // Flushing seems necessaary to have prefab property override status change without lag. Undo.FlushUndoRecordObjects(); prop.serializedObject.SetIsDifferentCacheDirty(); } } EditorGUI.indentLevel = oldIndent; } else { // if we're no longer showing tags, reset the tag field so that we can still search on the current // tag selection of the device slot. tagIndex = -1; } if (prop != null) { EditorGUI.EndProperty(); } }
void DrawControlSchemeGUI() { ControlScheme scheme = m_ActionMapEditCopy.controlSchemes[selectedScheme]; EditorGUI.BeginChangeCheck(); string schemeName = EditorGUILayout.TextField("Control Scheme Name", scheme.name); if (EditorGUI.EndChangeCheck()) { scheme.name = schemeName; } for (int i = 0; i < scheme.deviceSlots.Count; i++) { var deviceSlot = scheme.deviceSlots[i]; Rect rect = EditorGUILayout.GetControlRect(); if (Event.current.type == EventType.MouseDown && rect.Contains(Event.current.mousePosition)) { m_SelectedDeviceIndex = i; Repaint(); } if (m_SelectedDeviceIndex == i) { GUI.DrawTexture(rect, EditorGUIUtility.whiteTexture); } string[] tagNames = null; Vector2 tagMaxSize = Vector2.zero; if (deviceSlot.type != null && deviceSlot.type.value != null) { tagNames = InputDeviceUtility.GetDeviceTags(deviceSlot.type.value); if (tagNames != null) { GUIContent content = new GUIContent(); for (var j = 0; j < tagNames.Length; j++) { content.text = tagNames[j]; Vector2 size = EditorStyles.popup.CalcSize(content); tagMaxSize = Vector2.Max(size, tagMaxSize); } } } rect.width -= tagMaxSize.x; // Adjust width to leave room for tag EditorGUI.BeginChangeCheck(); Type t = TypeGUI.TypeField(rect, new GUIContent("Device Type"), typeof(InputDevice), deviceSlot.type); if (EditorGUI.EndChangeCheck()) { deviceSlot.type = t; } if (tagNames != null) { EditorGUI.BeginChangeCheck(); // We want to have the ability to unset a tag after specifying one, so add an "Any" option var popupTags = new string[tagNames.Length + 1]; popupTags[0] = "Any"; tagNames.CopyTo(popupTags, 1); int tagIndex = deviceSlot.tagIndex + 1; rect.x += rect.width; rect.width = tagMaxSize.x; tagIndex = EditorGUI.Popup( rect, tagIndex, popupTags); if (EditorGUI.EndChangeCheck()) { deviceSlot.tagIndex = tagIndex - 1; } } } // Device remove and add buttons EditorGUILayout.BeginHorizontal(); { GUILayout.Space(15 * EditorGUI.indentLevel); if (GUILayout.Button(Styles.iconToolbarMinus, GUIStyle.none)) { RemoveDevice(); } if (GUILayout.Button(Styles.iconToolbarPlus, GUIStyle.none)) { AddDevice(); } GUILayout.FlexibleSpace(); } EditorGUILayout.EndHorizontal(); // Pad this area with spacing so all control schemes use same heights, // and the actions table below doesn't move when switching control scheme. int maxDevices = 0; for (int i = 0; i < m_ActionMapEditCopy.controlSchemes.Count; i++) { maxDevices = Mathf.Max(maxDevices, m_ActionMapEditCopy.controlSchemes[i].deviceSlots.Count); } int extraLines = maxDevices - scheme.deviceSlots.Count; EditorGUILayout.GetControlRect(true, extraLines * (EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing)); }
void DrawActionGUI() { EditorGUI.BeginChangeCheck(); string name = EditorGUILayout.TextField("Name", selectedAction.name); if (EditorGUI.EndChangeCheck()) { selectedAction.name = name; RefreshPropertyNames(); } EditorGUI.BeginChangeCheck(); Rect rect = EditorGUILayout.GetControlRect(); Type type = TypeGUI.TypeField(rect, new GUIContent("Control Type"), typeof(InputControl), selectedAction.controlType); if (EditorGUI.EndChangeCheck()) { int actionIndex = m_ActionMapEditCopy.actions.IndexOf(selectedAction); bool anyBindings = false; for (int i = 0; i < m_ActionMapEditCopy.controlSchemes.Count; i++) { var scheme = m_ActionMapEditCopy.controlSchemes[i]; if (scheme.bindings[actionIndex] != null) { anyBindings = true; break; } } bool proceed = true; if (anyBindings) { proceed = EditorUtility.DisplayDialog( "Change Action Control Type", "Changing the Control Type will clear all bindings for this action ('" + selectedAction.name + "').", "Change", "Cancel"); } if (proceed) { selectedAction.controlType = type; m_ActionMapEditCopy.EnforceBindingsTypeConsistency(); } } EditorGUI.BeginChangeCheck(); rect = EditorGUILayout.GetControlRect(); bool combined = EditorGUI.Toggle(rect, new GUIContent("Combined"), selectedAction.combined); if (EditorGUI.EndChangeCheck()) { int actionIndex = m_ActionMapEditCopy.actions.IndexOf(selectedAction); bool anyBindings = false; for (int i = 0; i < m_ActionMapEditCopy.controlSchemes.Count; i++) { var scheme = m_ActionMapEditCopy.controlSchemes[i]; if (scheme.bindings[actionIndex] != null) { anyBindings = true; break; } } bool proceed = true; if (anyBindings) { proceed = EditorUtility.DisplayDialog( "Change Action", "Changing whether the Action is combined will clear all bindings for this action ('" + selectedAction.name + "').", "Change", "Cancel"); } if (proceed) { selectedAction.combined = combined; m_ActionMapEditCopy.EnforceBindingsTypeConsistency(); } } if (selectedAction.combined) { EditorGUILayout.Space(); EditorGUILayout.LabelField("Actions being combined"); EditorGUILayout.Space(); InputBinding binding = selectedAction.selfBinding; float height = binding.GetPropertyHeight(); rect = EditorGUILayout.GetControlRect(true, height); binding.OnGUI(rect, m_ActionMapEditCopy); } else { EditorGUILayout.Space(); EditorGUILayout.LabelField("Bindings for " + m_ActionMapEditCopy.controlSchemes[selectedScheme].name); EditorGUILayout.Space(); if (selectedScheme >= 0 && selectedScheme < m_ActionMapEditCopy.controlSchemes.Count) { int actionIndex = m_ActionMapEditCopy.actions.IndexOf(selectedAction); InputBinding binding = m_ActionMapEditCopy.controlSchemes[selectedScheme].bindings[actionIndex]; if (binding != null) { float height = binding.GetPropertyHeight(); rect = EditorGUILayout.GetControlRect(true, height); binding.OnGUI(rect, m_ActionMapEditCopy.controlSchemes[m_SelectedScheme]); } } } }
static GenericMenu GetMenu <C, T>(InputBinding <C, T> binding, IControlDomainSource domainSource, Action <InputBinding <C, T> > action) where C : InputControl <T> { GenericMenu menu = new GenericMenu(); Type[] derivedTypes = null; string[] derivedNames = null; Dictionary <Type, int> indicesOfDerivedTypes = null; TypeGUI.GetDerivedTypesInfo(typeof(InputBinding <C, T>), out derivedTypes, out derivedNames, out indicesOfDerivedTypes); Type bindingType = typeof(ControlReferenceBinding <C, T>); Type existingType = binding == null ? null : binding.GetType(); var reference = binding as ControlReferenceBinding <C, T>; // Add control references for devices. bool hasReferences = false; if (derivedTypes.Contains(bindingType)) { hasReferences = true; List <DomainEntry> domainEntries = domainSource.GetDomainEntries(); for (int i = 0; i < domainEntries.Count; i++) { int domainHash = domainEntries[i].hash; List <DomainEntry> controlEntries = domainSource.GetControlEntriesOfType(domainHash, typeof(C)); bool showFlatList = (domainEntries.Count <= 1 && controlEntries.Count <= 20); string prefix = showFlatList ? string.Empty : domainEntries[i].name + "/"; bool nonStandardizedSectionStart = false; for (int j = 0; j < controlEntries.Count; j++) { bool selected = (reference != null && reference.deviceKey == domainHash && reference.controlHash == controlEntries[j].hash); if (!nonStandardizedSectionStart && !controlEntries[j].standardized) { nonStandardizedSectionStart = true; menu.AddSeparator(prefix); } GUIContent name = new GUIContent(prefix + controlEntries[j].name); int index = j; // See "close over the loop variable". menu.AddItem(name, selected, () => { var newReference = new ControlReferenceBinding <C, T>(); newReference.deviceKey = domainHash; newReference.controlHash = controlEntries[index].hash; action(newReference); }); } } } if (derivedTypes.Length <= (hasReferences ? 1 : 0)) { return(menu); } menu.AddSeparator(""); // Add other control types. for (int i = 0; i < derivedTypes.Length; i++) { if (derivedTypes[i] != bindingType) { bool selected = (existingType == derivedTypes[i]); string name = NicifyBindingName(derivedNames[i]); int index = i; // See "close over the loop variable". menu.AddItem(new GUIContent(name), selected, () => { var newBinding = Activator.CreateInstance(derivedTypes[index]) as InputBinding <C, T>; action(newBinding); }); } } return(menu); }
void DrawControlSchemeGUI() { ControlScheme scheme = m_ActionMapEditCopy.controlSchemes[selectedScheme]; EditorGUI.BeginChangeCheck(); string schemeName = EditorGUILayout.TextField("Control Scheme Name", scheme.name); if (EditorGUI.EndChangeCheck()) { scheme.name = schemeName; } for (int i = 0; i < scheme.serializableDeviceTypes.Count; i++) { Rect rect = EditorGUILayout.GetControlRect(); if (Event.current.type == EventType.MouseDown && rect.Contains(Event.current.mousePosition)) { m_SelectedDeviceIndex = i; Repaint(); } if (m_SelectedDeviceIndex == i) { GUI.DrawTexture(rect, EditorGUIUtility.whiteTexture); } EditorGUI.BeginChangeCheck(); Type t = TypeGUI.TypeField(rect, new GUIContent("Device Type"), typeof(InputDevice), scheme.serializableDeviceTypes[i]); if (EditorGUI.EndChangeCheck()) { scheme.serializableDeviceTypes[i].value = t; } } // Device remove and add buttons EditorGUILayout.BeginHorizontal(); { GUILayout.Space(15 * EditorGUI.indentLevel); if (GUILayout.Button(Styles.iconToolbarMinus, GUIStyle.none)) { RemoveDevice(); } if (GUILayout.Button(Styles.iconToolbarPlus, GUIStyle.none)) { AddDevice(); } GUILayout.FlexibleSpace(); } EditorGUILayout.EndHorizontal(); // Pad this area with spacing so all control schemes use same heights, // and the actions table below doesn't move when switching control scheme. int maxDevices = 0; for (int i = 0; i < m_ActionMapEditCopy.controlSchemes.Count; i++) { maxDevices = Mathf.Max(maxDevices, m_ActionMapEditCopy.controlSchemes[i].serializableDeviceTypes.Count); } int extraLines = maxDevices - scheme.serializableDeviceTypes.Count; EditorGUILayout.GetControlRect(true, extraLines * (EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing)); }