372 lines
17 KiB
C#
372 lines
17 KiB
C#
using UnityEditor;
|
|
using UnityEngine;
|
|
|
|
namespace EasyChart.Editor
|
|
{
|
|
[CustomPropertyDrawer(typeof(AxisConfig))]
|
|
public class AxisConfigDrawer : PropertyDrawer
|
|
{
|
|
private static readonly string[] _labelFormatOptions =
|
|
{
|
|
"None",
|
|
"F0",
|
|
"F1",
|
|
"F2",
|
|
"N0",
|
|
"N2",
|
|
"P0",
|
|
"E2",
|
|
"Custom"
|
|
};
|
|
|
|
private static int ResolveLabelFormatIndex(string fmt, out bool isCustom)
|
|
{
|
|
if (string.IsNullOrEmpty(fmt))
|
|
{
|
|
isCustom = false;
|
|
return 0;
|
|
}
|
|
|
|
for (int i = 1; i < _labelFormatOptions.Length - 1; i++)
|
|
{
|
|
if (_labelFormatOptions[i] == fmt)
|
|
{
|
|
isCustom = false;
|
|
return i;
|
|
}
|
|
}
|
|
|
|
isCustom = true;
|
|
return _labelFormatOptions.Length - 1;
|
|
}
|
|
|
|
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
|
|
{
|
|
EditorGUI.BeginProperty(position, label, property);
|
|
|
|
float line = EditorGUIUtility.singleLineHeight;
|
|
float space = EditorGUIUtility.standardVerticalSpacing;
|
|
|
|
// Get all properties
|
|
var idProp = property.FindPropertyRelative("id");
|
|
var axisTypeProp = property.FindPropertyRelative("axisType");
|
|
|
|
var visibleProp = property.FindPropertyRelative("visible");
|
|
var colorProp = property.FindPropertyRelative("color");
|
|
var widthProp = property.FindPropertyRelative("width");
|
|
|
|
var labelStyleProp = property.FindPropertyRelative("labelStyle");
|
|
var labelPlacementProp = property.FindPropertyRelative("labelPlacement");
|
|
var labelsProp = property.FindPropertyRelative("labels");
|
|
var labelFormatProp = property.FindPropertyRelative("labelFormat");
|
|
|
|
var autoRangeMinProp = property.FindPropertyRelative("autoRangeMin");
|
|
var autoRangeMaxProp = property.FindPropertyRelative("autoRangeMax");
|
|
var autoRangeRoundingProp = property.FindPropertyRelative("autoRangeRounding");
|
|
var autoRangeUnitProp = property.FindPropertyRelative("autoRangeUnit");
|
|
var minValueProp = property.FindPropertyRelative("minValue");
|
|
var maxValueProp = property.FindPropertyRelative("maxValue");
|
|
|
|
var autoTicksProp = property.FindPropertyRelative("autoTicks");
|
|
var splitCountProp = property.FindPropertyRelative("splitCount");
|
|
|
|
var categoryAutoScrollProp = property.FindPropertyRelative("categoryAutoScroll");
|
|
var categorySmoothScrollProp = property.FindPropertyRelative("categorySmoothScroll");
|
|
var categoryScrollIntervalProp = property.FindPropertyRelative("categoryScrollInterval");
|
|
var categoryScrollStepProp = property.FindPropertyRelative("categoryScrollStep");
|
|
|
|
var showUnitProp = property.FindPropertyRelative("showUnit");
|
|
var unitTextProp = property.FindPropertyRelative("unitText");
|
|
var unitLabelStyleProp = property.FindPropertyRelative("unitLabelStyle");
|
|
|
|
Rect r = new Rect(position.x, position.y, position.width, line);
|
|
|
|
property.isExpanded = EditorGUI.Foldout(r, property.isExpanded, label, true);
|
|
r.y += line + space;
|
|
|
|
if (property.isExpanded)
|
|
{
|
|
EditorGUI.indentLevel++;
|
|
|
|
bool isCategoryAxis = axisTypeProp != null && axisTypeProp.enumValueIndex == (int)AxisType.Category;
|
|
bool isValueAxis = axisTypeProp == null || axisTypeProp.enumValueIndex == (int)AxisType.Value;
|
|
|
|
// ===== Section 1: Basic Info =====
|
|
EditorGUI.BeginDisabledGroup(true);
|
|
if (idProp != null) { EditorGUI.PropertyField(r, idProp); r.y += line + space; }
|
|
EditorGUI.EndDisabledGroup();
|
|
if (axisTypeProp != null) { EditorGUI.PropertyField(r, axisTypeProp); r.y += line + space; }
|
|
if (visibleProp != null) { EditorGUI.PropertyField(r, visibleProp); r.y += line + space; }
|
|
|
|
// ===== Section 2: Axis Line Style =====
|
|
r.y += space; // Add separator
|
|
EditorGUI.LabelField(r, "Axis Line", EditorStyles.boldLabel);
|
|
r.y += line + space;
|
|
if (colorProp != null) { EditorGUI.PropertyField(r, colorProp); r.y += line + space; }
|
|
if (widthProp != null) { EditorGUI.PropertyField(r, widthProp); r.y += line + space; }
|
|
|
|
// ===== Section 3: Range Settings (Value axis only) =====
|
|
if (isValueAxis)
|
|
{
|
|
r.y += space;
|
|
EditorGUI.LabelField(r, "Range", EditorStyles.boldLabel);
|
|
r.y += line + space;
|
|
|
|
if (autoRangeMinProp != null) { EditorGUI.PropertyField(r, autoRangeMinProp); r.y += line + space; }
|
|
if (autoRangeMinProp != null && !autoRangeMinProp.boolValue)
|
|
{
|
|
EditorGUI.indentLevel++;
|
|
if (minValueProp != null) { EditorGUI.PropertyField(r, minValueProp); r.y += line + space; }
|
|
EditorGUI.indentLevel--;
|
|
}
|
|
|
|
if (autoRangeMaxProp != null) { EditorGUI.PropertyField(r, autoRangeMaxProp); r.y += line + space; }
|
|
if (autoRangeMaxProp != null && !autoRangeMaxProp.boolValue)
|
|
{
|
|
EditorGUI.indentLevel++;
|
|
if (maxValueProp != null) { EditorGUI.PropertyField(r, maxValueProp); r.y += line + space; }
|
|
EditorGUI.indentLevel--;
|
|
}
|
|
|
|
if (autoRangeRoundingProp != null) { EditorGUI.PropertyField(r, autoRangeRoundingProp); r.y += line + space; }
|
|
if (autoRangeRoundingProp != null && autoRangeUnitProp != null)
|
|
{
|
|
if (autoRangeRoundingProp.enumValueIndex == 4)
|
|
{
|
|
EditorGUI.indentLevel++;
|
|
EditorGUI.PropertyField(r, autoRangeUnitProp);
|
|
r.y += line + space;
|
|
EditorGUI.indentLevel--;
|
|
}
|
|
}
|
|
}
|
|
|
|
// ===== Section 4: Ticks/Split Settings =====
|
|
r.y += space;
|
|
EditorGUI.LabelField(r, "Ticks", EditorStyles.boldLabel);
|
|
r.y += line + space;
|
|
|
|
if (autoTicksProp != null) { EditorGUI.PropertyField(r, autoTicksProp); r.y += line + space; }
|
|
if (autoTicksProp != null && !autoTicksProp.boolValue)
|
|
{
|
|
EditorGUI.indentLevel++;
|
|
if (splitCountProp != null)
|
|
{
|
|
var splitLabel = isCategoryAxis ? new GUIContent("VisibleCount") : new GUIContent("Split Count");
|
|
EditorGUI.PropertyField(r, splitCountProp, splitLabel);
|
|
r.y += line + space;
|
|
}
|
|
EditorGUI.indentLevel--;
|
|
}
|
|
|
|
// ===== Section 5: Label Settings =====
|
|
r.y += space;
|
|
EditorGUI.LabelField(r, "Labels", EditorStyles.boldLabel);
|
|
r.y += line + space;
|
|
|
|
if (labelStyleProp != null) { EditorGUI.PropertyField(r, labelStyleProp, true); r.y += EditorGUI.GetPropertyHeight(labelStyleProp, true) + space; }
|
|
if (labelPlacementProp != null) { EditorGUI.PropertyField(r, labelPlacementProp); r.y += line + space; }
|
|
|
|
if (labelFormatProp != null)
|
|
{
|
|
string current = labelFormatProp.stringValue;
|
|
bool custom;
|
|
int index = ResolveLabelFormatIndex(current, out custom);
|
|
|
|
var popupRect = EditorGUI.PrefixLabel(r, new GUIContent("LabelFormat"));
|
|
int newIndex = EditorGUI.Popup(popupRect, index, _labelFormatOptions);
|
|
r.y += line + space;
|
|
|
|
int customIndex = _labelFormatOptions.Length - 1;
|
|
if (newIndex != index)
|
|
{
|
|
if (newIndex == 0)
|
|
{
|
|
labelFormatProp.stringValue = string.Empty;
|
|
custom = false;
|
|
}
|
|
else if (newIndex == customIndex)
|
|
{
|
|
if (!custom) labelFormatProp.stringValue = string.Empty;
|
|
custom = true;
|
|
}
|
|
else
|
|
{
|
|
labelFormatProp.stringValue = _labelFormatOptions[newIndex];
|
|
custom = false;
|
|
}
|
|
}
|
|
|
|
if (newIndex == customIndex)
|
|
{
|
|
EditorGUI.indentLevel++;
|
|
string v = labelFormatProp.stringValue;
|
|
if (v == null) v = string.Empty;
|
|
string nv = EditorGUI.TextField(r, new GUIContent("Format"), v);
|
|
if (nv != v) labelFormatProp.stringValue = nv;
|
|
r.y += line + space;
|
|
EditorGUI.indentLevel--;
|
|
}
|
|
}
|
|
|
|
if (isCategoryAxis && labelsProp != null)
|
|
{
|
|
float h = EditorGUI.GetPropertyHeight(labelsProp, true);
|
|
EditorGUI.PropertyField(new Rect(r.x, r.y, r.width, h), labelsProp, new GUIContent("Category Labels"), true);
|
|
r.y += h + space;
|
|
}
|
|
|
|
// ===== Section 6: Unit Settings (Value axis only) =====
|
|
if (isValueAxis && showUnitProp != null)
|
|
{
|
|
r.y += space;
|
|
EditorGUI.LabelField(r, "Unit", EditorStyles.boldLabel);
|
|
r.y += line + space;
|
|
|
|
EditorGUI.PropertyField(r, showUnitProp);
|
|
r.y += line + space;
|
|
if (showUnitProp.boolValue)
|
|
{
|
|
EditorGUI.indentLevel++;
|
|
if (unitTextProp != null) { EditorGUI.PropertyField(r, unitTextProp); r.y += line + space; }
|
|
if (unitLabelStyleProp != null)
|
|
{
|
|
float uh = EditorGUI.GetPropertyHeight(unitLabelStyleProp, true);
|
|
EditorGUI.PropertyField(new Rect(r.x, r.y, r.width, uh), unitLabelStyleProp, true);
|
|
r.y += uh + space;
|
|
}
|
|
EditorGUI.indentLevel--;
|
|
}
|
|
}
|
|
|
|
// ===== Section 7: Category Scroll Settings (Category axis only) =====
|
|
if (isCategoryAxis && categoryAutoScrollProp != null)
|
|
{
|
|
r.y += space;
|
|
EditorGUI.LabelField(r, "Auto Scroll", EditorStyles.boldLabel);
|
|
r.y += line + space;
|
|
|
|
EditorGUI.PropertyField(r, categoryAutoScrollProp);
|
|
r.y += line + space;
|
|
if (categoryAutoScrollProp.boolValue)
|
|
{
|
|
EditorGUI.indentLevel++;
|
|
if (categorySmoothScrollProp != null) { EditorGUI.PropertyField(r, categorySmoothScrollProp); r.y += line + space; }
|
|
if (categoryScrollIntervalProp != null) { EditorGUI.PropertyField(r, categoryScrollIntervalProp); r.y += line + space; }
|
|
if (categoryScrollStepProp != null) { EditorGUI.PropertyField(r, categoryScrollStepProp); r.y += line + space; }
|
|
EditorGUI.indentLevel--;
|
|
}
|
|
}
|
|
|
|
EditorGUI.indentLevel--;
|
|
}
|
|
|
|
EditorGUI.EndProperty();
|
|
}
|
|
|
|
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
|
|
{
|
|
float line = EditorGUIUtility.singleLineHeight;
|
|
float space = EditorGUIUtility.standardVerticalSpacing;
|
|
|
|
float h = line; // Foldout
|
|
if (!property.isExpanded) return h;
|
|
|
|
var axisTypeProp = property.FindPropertyRelative("axisType");
|
|
var labelsProp = property.FindPropertyRelative("labels");
|
|
var labelStyleProp = property.FindPropertyRelative("labelStyle");
|
|
var labelFormatProp = property.FindPropertyRelative("labelFormat");
|
|
var autoRangeMinProp = property.FindPropertyRelative("autoRangeMin");
|
|
var autoRangeMaxProp = property.FindPropertyRelative("autoRangeMax");
|
|
var autoRangeRoundingProp = property.FindPropertyRelative("autoRangeRounding");
|
|
var autoRangeUnitProp = property.FindPropertyRelative("autoRangeUnit");
|
|
var autoTicksProp = property.FindPropertyRelative("autoTicks");
|
|
var categoryAutoScrollProp = property.FindPropertyRelative("categoryAutoScroll");
|
|
var showUnitProp = property.FindPropertyRelative("showUnit");
|
|
var unitLabelStyleProp = property.FindPropertyRelative("unitLabelStyle");
|
|
|
|
bool isCategoryAxis = axisTypeProp != null && axisTypeProp.enumValueIndex == (int)AxisType.Category;
|
|
bool isValueAxis = axisTypeProp == null || axisTypeProp.enumValueIndex == (int)AxisType.Value;
|
|
|
|
// Section 1: Basic Info
|
|
h += line + space; // id
|
|
h += line + space; // axisType
|
|
h += line + space; // visible
|
|
|
|
// Section 2: Axis Line (header + fields)
|
|
h += space + line + space; // header
|
|
h += line + space; // color
|
|
h += line + space; // width
|
|
|
|
// Section 3: Range (Value axis only)
|
|
if (isValueAxis)
|
|
{
|
|
h += space + line + space; // header
|
|
if (autoRangeMinProp != null)
|
|
{
|
|
h += line + space; // autoRangeMin
|
|
if (!autoRangeMinProp.boolValue) h += line + space; // minValue
|
|
}
|
|
if (autoRangeMaxProp != null)
|
|
{
|
|
h += line + space; // autoRangeMax
|
|
if (!autoRangeMaxProp.boolValue) h += line + space; // maxValue
|
|
}
|
|
if (autoRangeRoundingProp != null) h += line + space;
|
|
if (autoRangeRoundingProp != null && autoRangeUnitProp != null && autoRangeRoundingProp.enumValueIndex == 4)
|
|
{
|
|
h += line + space; // autoRangeUnit
|
|
}
|
|
}
|
|
|
|
// Section 4: Ticks (header + fields)
|
|
h += space + line + space; // header
|
|
if (autoTicksProp != null) h += line + space; // autoTicks
|
|
if (autoTicksProp != null && !autoTicksProp.boolValue) h += line + space; // splitCount/VisibleCount
|
|
|
|
// Section 5: Labels (header + fields)
|
|
h += space + line + space; // header
|
|
if (labelStyleProp != null) h += EditorGUI.GetPropertyHeight(labelStyleProp, true) + space;
|
|
h += line + space; // labelPlacement
|
|
h += line + space; // labelFormat
|
|
if (labelFormatProp != null)
|
|
{
|
|
bool custom;
|
|
int idx = ResolveLabelFormatIndex(labelFormatProp.stringValue, out custom);
|
|
if (idx == _labelFormatOptions.Length - 1) h += line + space; // custom format field
|
|
}
|
|
if (isCategoryAxis && labelsProp != null)
|
|
{
|
|
h += EditorGUI.GetPropertyHeight(labelsProp, true) + space; // Category Labels
|
|
}
|
|
|
|
// Section 6: Unit (Value axis only)
|
|
if (isValueAxis && showUnitProp != null)
|
|
{
|
|
h += space + line + space; // header
|
|
h += line + space; // showUnit
|
|
if (showUnitProp.boolValue)
|
|
{
|
|
h += line + space; // unitText
|
|
if (unitLabelStyleProp != null) h += EditorGUI.GetPropertyHeight(unitLabelStyleProp, true) + space;
|
|
}
|
|
}
|
|
|
|
// Section 7: Auto Scroll (Category axis only)
|
|
if (isCategoryAxis && categoryAutoScrollProp != null)
|
|
{
|
|
h += space + line + space; // header
|
|
h += line + space; // categoryAutoScroll
|
|
if (categoryAutoScrollProp.boolValue)
|
|
{
|
|
h += line + space; // categorySmoothScroll
|
|
h += line + space; // categoryScrollInterval
|
|
h += line + space; // categoryScrollStep
|
|
}
|
|
}
|
|
|
|
return h;
|
|
}
|
|
}
|
|
}
|