using Module.Inspector.Editor.Utilities; using UnityEditor; using UnityEngine; namespace Module.Inspector.Editor { [CustomPropertyDrawer(typeof(SliderAttribute))] internal sealed class SliderAttributeDrawer : DrawerPropertyDrawer { public override bool Draw(Rect position, DrawerPropertyAttribute attribute, SerializedProperty property, GUIContent label, EditorPropertyUtility.Result result) { var min = result.GetValueModifier(); var max = result.GetValueModifier(); if (min == null || max == null) return false; switch (property.propertyType) { case SerializedPropertyType.Integer: case SerializedPropertyType.Float: DrawRange(position, property, label, min, max); break; case SerializedPropertyType.Vector2: case SerializedPropertyType.Vector2Int: DrawerMinMax(position, property, label, min, max); break; default: return false; } return true; } public override string GetErrorMessage(SerializedProperty property) { switch (property.propertyType) { case SerializedPropertyType.Integer: case SerializedPropertyType.Float: case SerializedPropertyType.Vector2: case SerializedPropertyType.Vector2Int: return "Requires MinValue and MaxValue"; } return "Only supports integer, float, vector2 and vector2int"; } private void DrawRange(Rect position, SerializedProperty property, GUIContent label, MinValueAttribute minValueAttribute, MaxValueAttribute maxValueAttribute) { int indentLevel = EditorGUI.indentLevel; float indentSpacing = indentLevel * 15.0f; EditorGUI.indentLevel = 0; EditorGUI.BeginProperty(position, label, property); { float xMin = position.x + indentSpacing; var r0 = new Rect(xMin, position.y, EditorGUIUtility.labelWidth - indentSpacing + 2.0f, position.height); var r1 = new Rect(r0.xMax, r0.y, position.width - r0.width - indentSpacing, r0.height); EditorGUI.LabelField(r0, label); switch (property.propertyType) { case SerializedPropertyType.Integer: property.intValue = EditorGUI.IntSlider(r1, property.intValue, minValueAttribute.intValue, maxValueAttribute.intValue); break; case SerializedPropertyType.Float: property.floatValue = EditorGUI.Slider(r1, property.floatValue, minValueAttribute.floatValue, maxValueAttribute.floatValue); break; } } EditorGUI.EndProperty(); EditorGUI.indentLevel = indentLevel; } private void DrawerMinMax(Rect position, SerializedProperty property, GUIContent label, MinValueAttribute min, MaxValueAttribute max) { const float FLOAT_WIDTH = 50.0f; const float FLOAT_SPACING = 8.0f; int indentLevel = EditorGUI.indentLevel; float indentSpacing = indentLevel * 15.0f; EditorGUI.indentLevel = 0; EditorGUI.BeginProperty(position, label, property); { float xMin = position.x + indentSpacing; float width = position.width - indentSpacing; var r0 = new Rect(xMin, position.y, EditorGUIUtility.labelWidth - indentSpacing + 2.0f, position.height); var r1 = new Rect(r0.xMax, r0.y, FLOAT_WIDTH, r0.height); var r2 = new Rect(r1.xMax + FLOAT_SPACING, r1.y, width - r0.width - (FLOAT_WIDTH + FLOAT_SPACING) * 2, r1.height); var r3 = new Rect(r2.xMax + FLOAT_SPACING, r2.y, FLOAT_WIDTH, r2.height); EditorGUI.LabelField(r0, label); switch (property.propertyType) { case SerializedPropertyType.Vector2: Vector2 v = property.vector2Value; float minValue = v.x; float maxValue = v.y; minValue = EditorGUI.FloatField(r1, minValue); maxValue = EditorGUI.FloatField(r3, maxValue); EditorGUI.MinMaxSlider(r2, ref minValue, ref maxValue, min.floatValue, max.floatValue); v.x = minValue; v.y = maxValue; property.vector2Value = v; break; case SerializedPropertyType.Vector2Int: Vector2Int v2Int = property.vector2IntValue; float minIntValue = v2Int.x; float maxIntValue = v2Int.y; minIntValue = EditorGUI.IntField(r1, Mathf.RoundToInt(minIntValue)); maxIntValue = EditorGUI.IntField(r3, Mathf.RoundToInt(maxIntValue)); EditorGUI.MinMaxSlider(r2, ref minIntValue, ref maxIntValue, min.floatValue, max.floatValue); v2Int.x = Mathf.RoundToInt(minIntValue); v2Int.y = Mathf.RoundToInt(maxIntValue); property.vector2IntValue = v2Int; break; } } EditorGUI.EndProperty(); EditorGUI.indentLevel = indentLevel; } } }