using UnityEngine; using UnityEditor; using SplashEdit.RuntimeCode; using System.Linq; namespace SplashEdit.EditorCode { [CustomEditor(typeof(PSXSceneExporter))] public class PSXSceneExporterEditor : UnityEditor.Editor { private SerializedProperty gteScalingProp; private SerializedProperty sceneLuaProp; private SerializedProperty fogEnabledProp; private SerializedProperty fogColorProp; private SerializedProperty fogDensityProp; private SerializedProperty sceneTypeProp; private SerializedProperty cutscenesProp; private SerializedProperty loadingScreenProp; private SerializedProperty previewBVHProp; private SerializedProperty previewRoomsPortalsProp; private SerializedProperty bvhDepthProp; private bool showFog = true; private bool showCutscenes = true; private bool showDebug = false; private void OnEnable() { gteScalingProp = serializedObject.FindProperty("GTEScaling"); sceneLuaProp = serializedObject.FindProperty("SceneLuaFile"); fogEnabledProp = serializedObject.FindProperty("FogEnabled"); fogColorProp = serializedObject.FindProperty("FogColor"); fogDensityProp = serializedObject.FindProperty("FogDensity"); sceneTypeProp = serializedObject.FindProperty("SceneType"); cutscenesProp = serializedObject.FindProperty("Cutscenes"); loadingScreenProp = serializedObject.FindProperty("LoadingScreenPrefab"); previewBVHProp = serializedObject.FindProperty("PreviewBVH"); previewRoomsPortalsProp = serializedObject.FindProperty("PreviewRoomsPortals"); bvhDepthProp = serializedObject.FindProperty("BVHPreviewDepth"); } private void OnDisable() { } public override void OnInspectorGUI() { serializedObject.Update(); var exporter = (PSXSceneExporter)target; DrawExporterHeader(); EditorGUILayout.Space(4); DrawSceneSettings(); PSXEditorStyles.DrawSeparator(6, 6); DrawFogSection(exporter); PSXEditorStyles.DrawSeparator(6, 6); DrawCutscenesSection(); PSXEditorStyles.DrawSeparator(6, 6); DrawLoadingSection(); PSXEditorStyles.DrawSeparator(6, 6); DrawDebugSection(); PSXEditorStyles.DrawSeparator(6, 6); DrawSceneStats(); serializedObject.ApplyModifiedProperties(); } private void DrawExporterHeader() { EditorGUILayout.BeginVertical(PSXEditorStyles.CardStyle); EditorGUILayout.LabelField("Scene Exporter", PSXEditorStyles.CardHeaderStyle); EditorGUILayout.EndVertical(); } private void DrawSceneSettings() { EditorGUILayout.PropertyField(sceneTypeProp, new GUIContent("Scene Type")); bool isInterior = (PSXSceneType)sceneTypeProp.enumValueIndex == PSXSceneType.Interior; EditorGUILayout.LabelField( isInterior ? "Room/portal occlusion culling." : "BVH frustum culling.", PSXEditorStyles.RichLabel); EditorGUILayout.Space(4); EditorGUILayout.PropertyField(gteScalingProp, new GUIContent("GTE Scaling")); EditorGUILayout.PropertyField(sceneLuaProp, new GUIContent("Scene Lua")); if (sceneLuaProp.objectReferenceValue != null) { EditorGUILayout.BeginHorizontal(); GUILayout.Space(EditorGUI.indentLevel * 15); if (GUILayout.Button("Edit", EditorStyles.miniButtonLeft, GUILayout.Width(50))) AssetDatabase.OpenAsset(sceneLuaProp.objectReferenceValue); if (GUILayout.Button("Clear", EditorStyles.miniButtonRight, GUILayout.Width(50))) sceneLuaProp.objectReferenceValue = null; GUILayout.FlexibleSpace(); EditorGUILayout.EndHorizontal(); } } private void DrawFogSection(PSXSceneExporter exporter) { showFog = EditorGUILayout.Foldout(showFog, "Fog & Background", true, PSXEditorStyles.FoldoutHeader); if (!showFog) return; EditorGUI.indentLevel++; EditorGUILayout.PropertyField(fogColorProp, new GUIContent("Background Color", "Background clear color. Also used as the fog blend target when fog is enabled.")); EditorGUILayout.PropertyField(fogEnabledProp, new GUIContent("Distance Fog")); if (fogEnabledProp.boolValue) { EditorGUI.indentLevel++; EditorGUILayout.PropertyField(fogDensityProp, new GUIContent("Density")); float gteScale = exporter.GTEScaling; int density = Mathf.Clamp(exporter.FogDensity, 1, 10); float fogFarUnity = (8000f / density) * gteScale / 4096f; float fogNearUnity = fogFarUnity / 3f; EditorGUILayout.Space(2); EditorGUILayout.LabelField( $"GTE range: {fogNearUnity:F1} - {fogFarUnity:F1} units | " + $"{8000f / (density * 3f):F0} - {8000f / density:F0} SZ", PSXEditorStyles.RichLabel); EditorGUI.indentLevel--; } EditorGUI.indentLevel--; } private void DrawCutscenesSection() { showCutscenes = EditorGUILayout.Foldout(showCutscenes, "Cutscenes", true, PSXEditorStyles.FoldoutHeader); if (!showCutscenes) return; EditorGUI.indentLevel++; EditorGUILayout.PropertyField(cutscenesProp, new GUIContent("Clips"), true); EditorGUI.indentLevel--; } private void DrawLoadingSection() { EditorGUILayout.PropertyField(loadingScreenProp, new GUIContent("Loading Screen Prefab")); if (loadingScreenProp.objectReferenceValue != null) { var go = loadingScreenProp.objectReferenceValue as GameObject; if (go != null && go.GetComponentInChildren() == null) { EditorGUILayout.LabelField( "Prefab has no PSXCanvas component.", PSXEditorStyles.RichLabel); } } } private void DrawDebugSection() { showDebug = EditorGUILayout.Foldout(showDebug, "Debug", true, PSXEditorStyles.FoldoutHeader); if (!showDebug) return; EditorGUI.indentLevel++; EditorGUILayout.PropertyField(previewBVHProp, new GUIContent("Preview BVH")); if (previewBVHProp.boolValue) EditorGUILayout.PropertyField(bvhDepthProp, new GUIContent("BVH Depth")); EditorGUILayout.PropertyField(previewRoomsPortalsProp, new GUIContent("Preview Rooms/Portals")); EditorGUI.indentLevel--; } private void DrawSceneStats() { var exporters = FindObjectsByType(FindObjectsSortMode.None); int total = exporters.Length; int active = exporters.Count(e => e.IsActive); int staticCol = exporters.Count(e => e.CollisionType == PSXCollisionType.Static); int dynamicCol = exporters.Count(e => e.CollisionType == PSXCollisionType.Dynamic); int triggerBoxes = FindObjectsByType(FindObjectsSortMode.None).Length; EditorGUILayout.BeginVertical(PSXEditorStyles.CardStyle); EditorGUILayout.LabelField( $"{active}/{total} objects | {staticCol} static {dynamicCol} dynamic {triggerBoxes} triggers", PSXEditorStyles.RichLabel); EditorGUILayout.EndVertical(); } } }