2025-09-25 19:05:14 +08:00

194 lines
7.0 KiB
C#

using System.Linq;
using Unity.Mathematics;
using UnityEditor;
using UnityEditor.IMGUI.Controls;
using UnityEditorInternal;
using UnityEngine;
using UnityEngine.UIElements;
namespace X.Rendering.Scene
{
[CustomEditor(typeof(SceneEffect))]
public class SceneEffectEditorBase : Editor
{
ReorderableList lightList;
Transform transform;
int selectIndex = -1;
Vector4 mainLightDir = Vector4.zero;
SerializedProperty boundsProperty;
private BoxBoundsHandle boundsHandle = new();
public override VisualElement CreateInspectorGUI()
{
transform = (target as MonoBehaviour).transform;
var mainLight = GameObject.FindGameObjectWithTag("MainLight")?.GetComponent<Light>();
if (mainLight == null )
{
mainLight = GameObject.FindObjectsOfType<Light>().Where(l => l.type == LightType.Directional).First();
}
if(mainLight != null )
{
mainLightDir = (mainLight.transform.rotation * Vector3.forward).normalized;
mainLightDir.w = 1;
}
lightList = new ReorderableList(serializedObject, serializedObject.FindProperty("capsuleLights"), true, true, true, true);
lightList.onSelectCallback += (_) =>
{
Debug.Log($"{lightList.index}");
selectIndex = lightList.index;
};
lightList.onAddCallback += (_) =>
{
if (lightList.index == -1 && lightList.count == 0)
{
lightList.index = 0;
}
lightList.serializedProperty.InsertArrayElementAtIndex(lightList.index);
lightList.serializedProperty.GetArrayElementAtIndex(lightList.index).vector4Value = mainLightDir;
lightList.Select(lightList.index);
};
lightList.drawHeaderCallback = DrawHeader;
lightList.drawElementCallback = DrawListItems;
boundsProperty = serializedObject.FindProperty("Bounds");
return base.CreateInspectorGUI();
}
private void DrawListItems(Rect rect, int index, bool isActive, bool isFocused)
{
SerializedProperty element = lightList.serializedProperty.GetArrayElementAtIndex(index);
EditorGUI.LabelField(new Rect(rect.x, rect.y, 200, EditorGUIUtility.singleLineHeight), $"{element.vector4Value}");
}
private void DrawHeader(Rect rect)
{
string name = "光照方向";
EditorGUI.LabelField(rect, name);
}
public override void OnInspectorGUI()
{
serializedObject.Update();
base.OnInspectorGUI();
lightList.DoLayoutList();
serializedObject.ApplyModifiedProperties();
}
public void OnSceneGUI()
{
DrawBoundHandle();
if (selectIndex == -1 || lightList == null || selectIndex >= lightList?.serializedProperty.arraySize)
{
return;
}
SerializedProperty element = lightList.serializedProperty.GetArrayElementAtIndex(selectIndex);
var rot = new float4(element.vector4Value).xyz;
rot += DrawRotationHandle(element.vector4Value);
element.vector4Value = new float4(rot, element.vector4Value.w);
serializedObject.ApplyModifiedProperties();
}
protected float3 DrawRotationHandle(Vector3 vec)
{
EditorGUI.BeginChangeCheck();
var rotation = Quaternion.LookRotation(vec);
Vector3 newEuler = Vector3.zero;
Vector3 oldEuler = rotation.eulerAngles;
var col = Handles.color;
var pos = transform.position;
if (boundsProperty != null)
{
pos = boundsProperty.boundsValue.center;
}
Handles.color = Handles.xAxisColor;
newEuler.x = Handles.Disc(Quaternion.Euler(oldEuler.x, 0, 0), pos, Vector3.left, HandleUtility.GetHandleSize(pos) * 1.5f, false, 0.1f).eulerAngles.x;
Handles.color = Handles.yAxisColor;
newEuler.y = Handles.Disc(Quaternion.Euler(0, oldEuler.y, 0), pos, Vector3.up, HandleUtility.GetHandleSize(pos) * 1.5f, false, 0.1f).eulerAngles.y;
//var newRot = Handles.RotationHandle(rotation, pos);
EditorGUI.EndChangeCheck();
Handles.ConeHandleCap(0, pos, Quaternion.Euler(newEuler), HandleUtility.GetHandleSize(pos), EventType.Repaint);
Handles.color = col;
float3 delta;
var newVec = (Quaternion.Euler(newEuler) * Vector3.forward).normalized;
if (newVec != vec)
{
Undo.RecordObject(target, "DrawRotationHandle");
// Perform the handle move and update the serialized data
delta = newVec - vec;
}
else
{
delta = float3.zero;
}
return delta;
}
protected void DrawBoundHandle()
{
if (boundsProperty == null)
{
return;
}
EditorGUI.BeginChangeCheck();
var bounds = boundsProperty.boundsValue;
var col = Handles.color;
Handles.color = Color.green;
var newPos = Handles.PositionHandle(bounds.center, transform.rotation);
boundsHandle.center = bounds.center;
boundsHandle.size = bounds.size;
boundsHandle.DrawHandle();
if (EditorGUI.EndChangeCheck())
{
Undo.RecordObject(target, "DrawBoundHandle");
bounds.center = newPos;
bounds.size = boundsHandle.size;
boundsProperty.boundsValue = bounds;
}
boundsProperty.serializedObject.ApplyModifiedProperties();
Handles.color = col;
}
}
[CustomEditor(typeof(CapsuleShadowAreaEffect))]
public class MyClaCapsuleShadowAreaEffectsEditor : SceneEffectEditorBase
{
}
//[CustomPropertyDrawer(typeof(CapsuleShadowAreaSetting))]
//public class CapsuleShadowAreaSettingDrawer : PropertyDrawer
//{
// public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
// {
// EditorGUI.BeginProperty(position, label, property);
// EditorGUI.PropertyField(new Rect(position.x, position.y, 30, position.height), property.FindPropertyRelative("AmbientIntensity"), GUIContent.none);
// EditorGUI.PropertyField(new Rect(position.x + 35, position.y, 50, position.height), property.FindPropertyRelative("ShadowIntensity"), GUIContent.none);
// EditorGUI.PropertyField(new Rect(position.x + 90, position.y, position.width - 90, position.height), property.FindPropertyRelative("ShadowSharpness"), GUIContent.none);
// EditorGUI.EndProperty();
// }
//}
}