using UnityEditor; using UnityEditor.UI; namespace UnityEngine.UI { [CustomEditor(typeof(UXSlider), true)] [CanEditMultipleObjects] internal class UXSliderEditor : UXSelectableEditor { SerializedProperty m_Direction; SerializedProperty m_FillRect; SerializedProperty m_HandleRect; SerializedProperty m_MinValue; SerializedProperty m_MaxValue; SerializedProperty m_WholeNumbers; SerializedProperty m_Value; SerializedProperty m_OnValueChanged; SerializedProperty m_SmoothMovement; SerializedProperty m_SmoothSpeed; protected override void OnEnable() { base.OnEnable(); m_FillRect = serializedObject.FindProperty("m_FillRect"); m_HandleRect = serializedObject.FindProperty("m_HandleRect"); m_Direction = serializedObject.FindProperty("m_Direction"); m_MinValue = serializedObject.FindProperty("m_MinValue"); m_MaxValue = serializedObject.FindProperty("m_MaxValue"); m_WholeNumbers = serializedObject.FindProperty("m_WholeNumbers"); m_Value = serializedObject.FindProperty("m_Value"); m_OnValueChanged = serializedObject.FindProperty("m_OnValueChanged"); m_SmoothMovement = serializedObject.FindProperty("m_SmoothMovement"); m_SmoothSpeed = serializedObject.FindProperty("m_SmoothSpeed"); AppendToTab("Image", DrawImage); } protected override void OnDisable() { RemoveCallbackFromTab("Image", DrawImage); base.OnDisable(); } private void DrawImage() { EditorGUILayout.PropertyField(m_FillRect); EditorGUILayout.PropertyField(m_HandleRect); if (m_FillRect.objectReferenceValue != null || m_HandleRect.objectReferenceValue != null) { EditorGUI.BeginChangeCheck(); EditorGUILayout.PropertyField(m_Direction); if (EditorGUI.EndChangeCheck()) { Undo.RecordObjects(serializedObject.targetObjects, "Change Slider Direction"); Slider.Direction direction = (Slider.Direction)m_Direction.enumValueIndex; foreach (var obj in serializedObject.targetObjects) { UXSlider slider = obj as UXSlider; slider.SetDirection(direction, true); } } EditorGUI.BeginChangeCheck(); float newMin = EditorGUILayout.FloatField("Min Value", m_MinValue.floatValue); if (EditorGUI.EndChangeCheck()) { if (m_WholeNumbers.boolValue ? Mathf.Round(newMin) < m_MaxValue.floatValue : newMin < m_MaxValue.floatValue) { m_MinValue.floatValue = newMin; if (m_Value.floatValue < newMin) m_Value.floatValue = newMin; } } EditorGUI.BeginChangeCheck(); float newMax = EditorGUILayout.FloatField("Max Value", m_MaxValue.floatValue); if (EditorGUI.EndChangeCheck()) { if (m_WholeNumbers.boolValue ? Mathf.Round(newMax) > m_MinValue.floatValue : newMax > m_MinValue.floatValue) { m_MaxValue.floatValue = newMax; if (m_Value.floatValue > newMax) m_Value.floatValue = newMax; } } EditorGUILayout.PropertyField(m_WholeNumbers); bool areMinMaxEqual = (m_MinValue.floatValue == m_MaxValue.floatValue); if (areMinMaxEqual) EditorGUILayout.HelpBox("Min Value and Max Value cannot be equal.", MessageType.Warning); if (m_WholeNumbers.boolValue) m_Value.floatValue = Mathf.Round(m_Value.floatValue); EditorGUI.BeginDisabledGroup(areMinMaxEqual); EditorGUI.BeginChangeCheck(); EditorGUILayout.Slider(m_Value, m_MinValue.floatValue, m_MaxValue.floatValue); if (EditorGUI.EndChangeCheck()) { serializedObject.ApplyModifiedProperties(); foreach (var t in targets) { if (t is UXSlider slider) { slider.onValueChanged?.Invoke(slider.value); } } } EditorGUI.EndDisabledGroup(); EditorGUILayout.Space(); EditorGUILayout.LabelField("Move Smoothing (Gamepad / Keys)", EditorStyles.boldLabel); EditorGUILayout.PropertyField(m_SmoothMovement, new GUIContent("Enable Smooth Movement")); using (new EditorGUI.DisabledScope(m_SmoothMovement.boolValue == false)) { EditorGUILayout.PropertyField(m_SmoothSpeed, new GUIContent("Smooth Speed (value/sec)")); if (m_WholeNumbers.boolValue && m_SmoothMovement.boolValue) { EditorGUILayout.HelpBox("Note: wholeNumbers is enabled — smooth movement will be disabled at runtime (values stay integer).", MessageType.Info); } } bool warning = false; foreach (var obj in serializedObject.targetObjects) { UXSlider slider = obj as UXSlider; Slider.Direction dir = slider.direction; if (dir == Slider.Direction.LeftToRight || dir == Slider.Direction.RightToLeft) warning = (slider.navigation.mode != UXNavigation.Mode.Automatic && (slider.FindSelectableOnLeft() != null || slider.FindSelectableOnRight() != null)); else warning = (slider.navigation.mode != UXNavigation.Mode.Automatic && (slider.FindSelectableOnDown() != null || slider.FindSelectableOnUp() != null)); } if (warning) EditorGUILayout.HelpBox("The selected slider direction conflicts with navigation. Not all navigation options may work.", MessageType.Warning); EditorGUILayout.Space(); EditorGUILayout.PropertyField(m_OnValueChanged); } else { EditorGUILayout.HelpBox("Specify a RectTransform for the slider fill or the slider handle or both. Each must have a parent RectTransform that it can slide within.", MessageType.Info); } serializedObject.ApplyModifiedProperties(); } } }