123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198 |
- #if UNITY_EDITOR
- using UnityEditor;
-
- namespace UnityEngine.InputSystem.Editor
- {
- /// <summary>
- /// A custom property drawer for <see cref="InputActionProperty"/>.
- /// </summary>
- /// <remarks>
- /// Selectively draws the <see cref="InputActionReference"/> and/or the <see cref="InputAction"/>
- /// underlying the property, based on whether the property is set to use a reference or not.
- /// The drawer also allows for drawing in different layouts, chosen through Project Settings.
- /// </remarks>
- /// <seealso cref="InputSettings.InputActionPropertyDrawerMode"/>
- [CustomPropertyDrawer(typeof(InputActionProperty))]
- internal class InputActionPropertyDrawer : PropertyDrawer
- {
- public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
- {
- if (property == null)
- throw new System.ArgumentNullException(nameof(property));
-
- var drawerMode = InputSystem.settings.inputActionPropertyDrawerMode;
- switch (drawerMode)
- {
- case InputSettings.InputActionPropertyDrawerMode.Compact:
- default:
- return GetCompactHeight(property);
-
- case InputSettings.InputActionPropertyDrawerMode.MultilineEffective:
- case InputSettings.InputActionPropertyDrawerMode.MultilineBoth:
- return GetMultilineHeight(property, drawerMode == InputSettings.InputActionPropertyDrawerMode.MultilineEffective);
- }
- }
-
- public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
- {
- if (property == null)
- throw new System.ArgumentNullException(nameof(property));
-
- // Using BeginProperty / EndProperty on the parent property means that
- // prefab override logic works on the entire property.
- label = EditorGUI.BeginProperty(position, label, property);
-
- var drawerMode = InputSystem.settings.inputActionPropertyDrawerMode;
- switch (drawerMode)
- {
- case InputSettings.InputActionPropertyDrawerMode.Compact:
- default:
- DrawCompactGUI(position, property, label);
- break;
-
- case InputSettings.InputActionPropertyDrawerMode.MultilineEffective:
- case InputSettings.InputActionPropertyDrawerMode.MultilineBoth:
- DrawMultilineGUI(position, property, label, drawerMode == InputSettings.InputActionPropertyDrawerMode.MultilineEffective);
- break;
- }
-
- EditorGUI.EndProperty();
- }
-
- static float GetCompactHeight(SerializedProperty property)
- {
- var useReference = property.FindPropertyRelative("m_UseReference");
- var effectiveProperty = useReference.boolValue ? property.FindPropertyRelative("m_Reference") : property.FindPropertyRelative("m_Action");
- return EditorGUI.GetPropertyHeight(effectiveProperty);
- }
-
- static float GetMultilineHeight(SerializedProperty property, bool showEffectiveOnly)
- {
- var height = 0f;
-
- // Field label.
- height += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;
-
- // "Use Reference" toggle.
- height += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;
-
- // We show either the InputAction property drawer or InputActionReference drawer (default object field).
- var useReference = property.FindPropertyRelative("m_UseReference");
- var reference = property.FindPropertyRelative("m_Reference");
- var action = property.FindPropertyRelative("m_Action");
- if (showEffectiveOnly)
- {
- var effectiveProperty = useReference.boolValue ? reference : action;
- height += EditorGUI.GetPropertyHeight(effectiveProperty);
- }
- else
- {
- height += EditorGUI.GetPropertyHeight(reference) + EditorGUI.GetPropertyHeight(action);
- }
-
- return height;
- }
-
- static void DrawCompactGUI(Rect position, SerializedProperty property, GUIContent label)
- {
- position = EditorGUI.PrefixLabel(position, label);
-
- var useReference = property.FindPropertyRelative("m_UseReference");
- var effectiveProperty = useReference.boolValue ? property.FindPropertyRelative("m_Reference") : property.FindPropertyRelative("m_Action");
-
- // Calculate rect for configuration button
- var buttonRect = position;
- var popupStyle = Styles.popup;
- buttonRect.yMin += popupStyle.margin.top + 1f;
- buttonRect.width = popupStyle.fixedWidth + popupStyle.margin.right;
- buttonRect.height = EditorGUIUtility.singleLineHeight;
- position.xMin = buttonRect.xMax;
-
- // Don't make child fields be indented
- var indent = EditorGUI.indentLevel;
- EditorGUI.indentLevel = 0;
-
- // Using BeginProperty / EndProperty on the popup button allows the user to
- // revert prefab overrides to Use Reference by right-clicking the configuration button.
- EditorGUI.BeginProperty(buttonRect, GUIContent.none, useReference);
- using (var check = new EditorGUI.ChangeCheckScope())
- {
- var newPopupIndex = EditorGUI.Popup(buttonRect, GetCompactPopupIndex(useReference), Contents.compactPopupOptions, popupStyle);
- if (check.changed)
- useReference.boolValue = IsUseReference(newPopupIndex);
- }
- EditorGUI.EndProperty();
-
- EditorGUI.PropertyField(position, effectiveProperty, GUIContent.none);
-
- // Set indent back to what it was
- EditorGUI.indentLevel = indent;
- }
-
- static void DrawMultilineGUI(Rect position, SerializedProperty property, GUIContent label, bool showEffectiveOnly)
- {
- const float kIndent = 15f;
-
- var titleRect = position;
- titleRect.height = EditorGUIUtility.singleLineHeight;
-
- var useReference = property.FindPropertyRelative("m_UseReference");
- var useReferenceToggleRect = position;
- useReferenceToggleRect.x += kIndent;
- useReferenceToggleRect.width -= kIndent;
- useReferenceToggleRect.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing;
- useReferenceToggleRect.height = EditorGUI.GetPropertyHeight(useReference);
-
- var firstValueRect = position;
- firstValueRect.x += kIndent;
- firstValueRect.width -= kIndent;
- firstValueRect.y += (titleRect.height + useReferenceToggleRect.height) + (EditorGUIUtility.standardVerticalSpacing * 2f);
-
- var reference = property.FindPropertyRelative("m_Reference");
- var action = property.FindPropertyRelative("m_Action");
-
- // Draw the Use Reference toggle.
- EditorGUI.LabelField(titleRect, label);
- EditorGUI.PropertyField(useReferenceToggleRect, useReference);
-
- if (showEffectiveOnly)
- {
- // Draw only the Reference or Action underlying the property, whichever is the effective one.
- var effectiveProperty = useReference.boolValue ? reference : action;
- firstValueRect.height = EditorGUI.GetPropertyHeight(effectiveProperty);
-
- EditorGUI.PropertyField(firstValueRect, effectiveProperty);
- }
- else
- {
- // Draw the Action followed by the Reference.
- firstValueRect.height = EditorGUI.GetPropertyHeight(action);
-
- var referenceRect = firstValueRect;
- referenceRect.y += firstValueRect.height + EditorGUIUtility.standardVerticalSpacing;
- referenceRect.height = EditorGUI.GetPropertyHeight(reference);
-
- EditorGUI.PropertyField(firstValueRect, action);
- EditorGUI.PropertyField(referenceRect, reference);
- }
- }
-
- // 0 == Use Reference, 1 == Use Action
- // Keep synced with Contents.compactPopupOptions.
- static int GetCompactPopupIndex(SerializedProperty useReference) => useReference.boolValue ? 0 : 1;
- static bool IsUseReference(int index) => index == 0;
-
- static class Contents
- {
- static readonly GUIContent s_UseReference = EditorGUIUtility.TrTextContent("Use Reference");
- static readonly GUIContent s_UseAction = EditorGUIUtility.TrTextContent("Use Action");
- public static readonly GUIContent[] compactPopupOptions = { s_UseReference, s_UseAction };
- }
-
- static class Styles
- {
- public static readonly GUIStyle popup = new GUIStyle("PaneOptions") { imagePosition = ImagePosition.ImageOnly };
- }
- }
- }
- #endif // UNITY_EDITOR
|