Files
2026-07-09 17:08:14 +08:00

251 lines
9.7 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using XericLibrary.Runtime.UIGraph;
namespace XericLibraryEditor.XericComponent
{
[CustomEditor(typeof(UICurveRenderer))]
public class UICurveRendererEditor : Editor
{
private UICurveRenderer script;
// MaskableGraphic 基础属性
private SerializedProperty m_RaycastTarget;
private SerializedProperty m_Maskable;
private SerializedProperty m_Material;
private SerializedProperty m_Color;
// 曲线属性
private SerializedProperty controlPointsProp;
private SerializedProperty startColorProp;
private SerializedProperty endColorProp;
private SerializedProperty tessellationSegmentsProp;
private SerializedProperty arrowsProp;
private SerializedProperty autoRebuildProp;
// 折叠状态
private bool m_ControlPointsFoldout = true;
private bool m_ArrowsFoldout = true;
protected void OnEnable()
{
script = (UICurveRenderer)target;
FetchProperties();
}
private void FetchProperties()
{
m_RaycastTarget = serializedObject.FindProperty("m_RaycastTarget");
m_Maskable = serializedObject.FindProperty("m_Maskable");
m_Material = serializedObject.FindProperty("m_Material");
m_Color = serializedObject.FindProperty("m_Color");
controlPointsProp = serializedObject.FindProperty("controlPoints");
startColorProp = serializedObject.FindProperty("startColor");
endColorProp = serializedObject.FindProperty("endColor");
tessellationSegmentsProp = serializedObject.FindProperty("tessellationSegments");
arrowsProp = serializedObject.FindProperty("arrows");
autoRebuildProp = serializedObject.FindProperty("autoRebuild");
}
public override void OnInspectorGUI()
{
// 确保 SerializedProperty 已初始化
if (arrowsProp == null)
FetchProperties();
serializedObject.Update();
// MaskableGraphic 基础属性
EditorGUILayout.PropertyField(m_RaycastTarget);
EditorGUILayout.PropertyField(m_Maskable);
EditorGUILayout.PropertyField(m_Material, new GUIContent("材质"));
EditorGUILayout.PropertyField(m_Color, new GUIContent("顶点颜色"));
EditorGUILayout.Space();
EditorGUILayout.LabelField("颜色", EditorStyles.boldLabel);
EditorGUILayout.PropertyField(startColorProp, new GUIContent("起始颜色"));
EditorGUILayout.PropertyField(endColorProp, new GUIContent("结束颜色"));
EditorGUILayout.Space();
EditorGUILayout.LabelField("曲线参数", EditorStyles.boldLabel);
EditorGUILayout.PropertyField(tessellationSegmentsProp, new GUIContent("细分段数"));
// 控制点折叠列表
EditorGUILayout.Space();
m_ControlPointsFoldout = EditorGUILayout.Foldout(m_ControlPointsFoldout,
new GUIContent($"控制点 ({GetArrayLength(controlPointsProp)})"), true);
if (m_ControlPointsFoldout)
{
EditorGUI.indentLevel++;
DrawControlPointsList();
EditorGUI.indentLevel--;
}
// 箭头折叠列表
EditorGUILayout.Space();
m_ArrowsFoldout = EditorGUILayout.Foldout(m_ArrowsFoldout,
new GUIContent($"箭头装饰 ({arrowsProp.arraySize})"), true);
if (m_ArrowsFoldout)
{
EditorGUI.indentLevel++;
DrawArrowsList();
EditorGUI.indentLevel--;
}
EditorGUILayout.Space();
EditorGUILayout.PropertyField(autoRebuildProp, new GUIContent("自动刷新"));
serializedObject.ApplyModifiedProperties();
if (GUI.changed)
{
if (script.autoRebuild && script.isActiveAndEnabled)
{
script.RebuildCurve();
}
}
}
private int GetArrayLength(SerializedProperty prop)
{
if (prop == null) return 0;
return prop.arraySize;
}
private void DrawControlPointsList()
{
if (controlPointsProp == null) return;
int count = controlPointsProp.arraySize;
int newCount = EditorGUILayout.IntField("数量", count);
if (newCount < 2) newCount = 2;
if (newCount != count)
{
controlPointsProp.arraySize = newCount;
}
for (int i = 0; i < controlPointsProp.arraySize; i++)
{
EditorGUILayout.BeginHorizontal();
var cp = controlPointsProp.GetArrayElementAtIndex(i);
// Vector3: (x,y)=位置, z=宽度
Vector3 val = cp.vector3Value;
EditorGUI.BeginChangeCheck();
val = EditorGUILayout.Vector3Field($"CP {i}", val);
if (EditorGUI.EndChangeCheck())
cp.vector3Value = val;
// 删除按钮(至少保留 2 个控制点)
GUI.enabled = controlPointsProp.arraySize > 2;
if (GUILayout.Button("×", GUILayout.Width(25)))
{
RemoveControlPointAt(i);
}
GUI.enabled = true;
EditorGUILayout.EndHorizontal();
}
// 添加按钮
if (GUILayout.Button("+ 添加控制点"))
{
int idx = controlPointsProp.arraySize;
controlPointsProp.arraySize++;
if (idx > 0)
{
var prev = controlPointsProp.GetArrayElementAtIndex(idx - 1);
var prev2 = idx > 1 ? controlPointsProp.GetArrayElementAtIndex(idx - 2) : prev;
Vector3 prevVal = prev.vector3Value;
Vector3 prev2Val = prev2.vector3Value;
Vector3 dir = new Vector3(
(prevVal.x - prev2Val.x) * 0.5f,
(prevVal.y - prev2Val.y) * 0.5f,
10f);
dir = dir.normalized * 50f;
var newCp = controlPointsProp.GetArrayElementAtIndex(idx);
newCp.vector3Value = new Vector3(
prevVal.x + dir.x,
prevVal.y + dir.y,
prevVal.z);
}
else
{
var newCp = controlPointsProp.GetArrayElementAtIndex(0);
newCp.vector3Value = Vector3.zero;
}
}
}
private void RemoveControlPointAt(int index)
{
controlPointsProp.DeleteArrayElementAtIndex(index);
}
private void DrawArrowsList()
{
if (arrowsProp == null) return;
for (int i = 0; i < arrowsProp.arraySize; i++)
{
var arrow = arrowsProp.GetArrayElementAtIndex(i);
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
var shapeProp = arrow.FindPropertyRelative("shape");
var reversedProp = arrow.FindPropertyRelative("reversed");
var progressProp = arrow.FindPropertyRelative("progress");
var widthProp = arrow.FindPropertyRelative("width");
var heightProp = arrow.FindPropertyRelative("height");
var depthProp = arrow.FindPropertyRelative("depthCompensation");
var colorProp = arrow.FindPropertyRelative("color");
EditorGUILayout.PropertyField(shapeProp, new GUIContent("形状"));
EditorGUILayout.PropertyField(reversedProp, new GUIContent("反向"));
EditorGUILayout.Slider(progressProp, 0f, 1f, new GUIContent("进度"));
EditorGUILayout.PropertyField(widthProp, new GUIContent("宽度"));
EditorGUILayout.PropertyField(heightProp, new GUIContent("高度"));
EditorGUILayout.Slider(depthProp, -1f, 1f, new GUIContent("深度补偿"));
EditorGUILayout.PropertyField(colorProp, new GUIContent("颜色"));
if (GUILayout.Button("× 删除此箭头"))
{
arrowsProp.DeleteArrayElementAtIndex(i);
break;
}
EditorGUILayout.EndVertical();
EditorGUILayout.Space(2);
}
if (GUILayout.Button("+ 添加箭头"))
{
int idx = arrowsProp.arraySize;
arrowsProp.arraySize++;
var newArrow = arrowsProp.GetArrayElementAtIndex(idx);
var shapeProp = newArrow.FindPropertyRelative("shape");
var reversedProp = newArrow.FindPropertyRelative("reversed");
var progressProp = newArrow.FindPropertyRelative("progress");
var widthProp = newArrow.FindPropertyRelative("width");
var heightProp = newArrow.FindPropertyRelative("height");
var depthProp = newArrow.FindPropertyRelative("depthCompensation");
var colorProp = newArrow.FindPropertyRelative("color");
shapeProp.enumValueIndex = 0;
reversedProp.boolValue = false;
progressProp.floatValue = 0.5f;
widthProp.floatValue = 20f;
heightProp.floatValue = 20f;
depthProp.floatValue = 0f;
colorProp.colorValue = Color.white;
}
}
}
}