using System.Linq; using Unity.Mathematics; using UnityEditor; using UnityEditor.EditorTools; 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(); LightData[] lightDatas = null; public override VisualElement CreateInspectorGUI() { transform = (target as MonoBehaviour).transform; var mainLight = GameObject.FindGameObjectWithTag("MainLight")?.GetComponent(); if (mainLight == null) { mainLight = GameObject.FindObjectsOfType().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; }; var t = serializedObject.targetObject.GetType().GetField("capsuleLights", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance); lightDatas = t.GetValue(serializedObject.targetObject) as LightData[]; lightList.onAddCallback += (_) => { if (lightList.index == -1 && lightList.count == 0) { lightList.index = 0; } lightList.serializedProperty.InsertArrayElementAtIndex(lightList.index); serializedObject.ApplyModifiedProperties(); var light = new LightData() { isPointLight = true, lightIntensity = 1, lightPosition = transform.position + Vector3.up }; if (lightDatas != null) { lightDatas[lightList.index] = light; 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) { if(index < 0 ) { return; } EditorGUI.BeginChangeCheck(); var light = lightDatas[index]; float x = rect.x; //EditorGUI.LabelField(new Rect(x, rect.y, 50, EditorGUIUtility.singleLineHeight), "点光"); //x += 50; EditorGUI.LabelField(new Rect(x, rect.y, 150, EditorGUIUtility.singleLineHeight), $"{light.lightPosition}"); x += 140; light.lightIntensity = EditorGUI.Slider(new Rect(x, rect.y, 200, EditorGUIUtility.singleLineHeight), light.lightIntensity, 0.2f, 2); x += 210; light.isPointLight = EditorGUI.ToggleLeft(new Rect(x, rect.y, 50, EditorGUIUtility.singleLineHeight), "点光", light.isPointLight); if (EditorGUI.EndChangeCheck()) { Undo.RecordObject(target, "DrawListItems"); CallValidate(); } } private void DrawHeader(Rect rect) { string name = "光照方向"; EditorGUI.LabelField(rect, name); } public override void OnInspectorGUI() { serializedObject.Update(); base.OnInspectorGUI(); lightList.DoLayoutList(); serializedObject.ApplyModifiedProperties(); } private void OnDestroy() { Tools.hidden = false; } public void OnSceneGUI() { DrawBoundHandle(); if (selectIndex == -1 || lightList == null || selectIndex >= lightList?.serializedProperty.arraySize) { return; } var light = lightDatas[selectIndex]; Tools.hidden = true; if (!light.isPointLight) { var rot = (float3)light.lightPosition; rot += DrawRotationHandle(light.lightPosition); light.lightPosition = rot; } else { var pos = (float3)light.lightPosition; pos += DrawPositionHandle(light.lightPosition); light.lightPosition = pos; } serializedObject.ApplyModifiedProperties(); } protected void CallValidate() { target.GetType().GetMethod("OnValidate", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance).Invoke(target, null); } protected float3 DrawPositionHandle(Vector3 vec) { EditorGUI.BeginChangeCheck(); var newPos = Handles.PositionHandle(vec, Quaternion.identity); float3 delta = float3.zero; if (EditorGUI.EndChangeCheck()) { Undo.RecordObject(target, "DrawPositionHandle"); delta = newPos - vec; CallValidate(); } return delta; } 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 = float3.zero; var newVec = (Quaternion.Euler(newEuler) * Vector3.forward).normalized; if (newVec != vec) { Undo.RecordObject(target, "DrawRotationHandle"); delta = newVec - vec; CallValidate(); } 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(); // } //} }