using UnityEngine; using UnityEditor; using SplashEdit.RuntimeCode; namespace SplashEdit.EditorCode { /// /// Custom inspector for PSXSceneExporter. /// When the component is selected and fog is enabled, activates a Unity scene-view /// fog preview that approximates the PS1 linear fog distances. /// /// Fog distance mapping: /// fogFarSZ = 8000 / FogDensity (GTE SZ units) /// fogNearSZ = fogFarSZ / 3 /// SZ is 20.12 fixed-point: SZ = (unityCoord / GTEScaling) * 4096 /// => unityDist = SZ * GTEScaling / 4096 /// => Unity fog near = (8000 / (FogDensity * 3)) * GTEScaling / 4096 /// => Unity fog far = (8000 / FogDensity) * GTEScaling / 4096 /// [CustomEditor(typeof(PSXSceneExporter))] public class PSXSceneExporterEditor : UnityEditor.Editor { // Saved RenderSettings state so we can restore it on deselect. private bool _savedFog; private Color _savedFogColor; private FogMode _savedFogMode; private float _savedFogStart; private float _savedFogEnd; private bool _previewActive = false; private void OnEnable() { SaveAndApplyFogPreview(); // Re-apply whenever the scene is repainted (handles inspector value changes). EditorApplication.update += OnEditorUpdate; } private void OnDisable() { EditorApplication.update -= OnEditorUpdate; RestoreFog(); } private void OnEditorUpdate() { // Keep the preview in sync when the user tweaks values in the inspector. if (_previewActive) ApplyFogPreview(); } private void SaveAndApplyFogPreview() { _savedFog = RenderSettings.fog; _savedFogColor = RenderSettings.fogColor; _savedFogMode = RenderSettings.fogMode; _savedFogStart = RenderSettings.fogStartDistance; _savedFogEnd = RenderSettings.fogEndDistance; _previewActive = true; ApplyFogPreview(); } private void ApplyFogPreview() { var exporter = (PSXSceneExporter)target; if (exporter == null) return; if (!exporter.FogEnabled) { // Fog disabled on the component - turn off the preview. RenderSettings.fog = false; return; } float gteScale = exporter.GTEScaling; int density = Mathf.Clamp(exporter.FogDensity, 1, 10); // fogFarSZ in GTE SZ units (20.12 fp); convert to Unity world-space. // SZ = (unityDist / GTEScaling) * 4096, so unityDist = SZ * GTEScaling / 4096 float fogFarSZ = 8000f / density; float fogNearSZ = fogFarSZ / 3f; float fogFarUnity = fogFarSZ * gteScale / 4096f; float fogNearUnity = fogNearSZ * gteScale / 4096f; RenderSettings.fog = true; RenderSettings.fogColor = exporter.FogColor; RenderSettings.fogMode = FogMode.Linear; RenderSettings.fogStartDistance = fogNearUnity; RenderSettings.fogEndDistance = fogFarUnity; } private void RestoreFog() { if (!_previewActive) return; _previewActive = false; RenderSettings.fog = _savedFog; RenderSettings.fogColor = _savedFogColor; RenderSettings.fogMode = _savedFogMode; RenderSettings.fogStartDistance = _savedFogStart; RenderSettings.fogEndDistance = _savedFogEnd; } public override void OnInspectorGUI() { serializedObject.Update(); DrawDefaultInspector(); // Show computed fog distances when fog is enabled, so the user // can see exactly what range the preview represents. var exporter = (PSXSceneExporter)target; if (exporter.FogEnabled) { EditorGUILayout.Space(4); EditorGUILayout.BeginVertical(EditorStyles.helpBox); GUILayout.Label("Fog Preview (active in Scene view)", EditorStyles.boldLabel); float gteScale = exporter.GTEScaling; int density = Mathf.Clamp(exporter.FogDensity, 1, 10); float fogFarUnity = (8000f / density) * gteScale / 4096f; float fogNearUnity = fogFarUnity / 3f; EditorGUILayout.LabelField("Near distance", $"{fogNearUnity:F1} Unity units"); EditorGUILayout.LabelField("Far distance", $"{fogFarUnity:F1} Unity units"); EditorGUILayout.LabelField("(PS1 SZ range)", $"{8000f / (density * 3f):F0} - {8000f / density:F0} GTE units"); EditorGUILayout.EndVertical(); // Keep preview applied as values may have changed. ApplyFogPreview(); } else { // Make sure preview is off when fog is disabled. RenderSettings.fog = false; } serializedObject.ApplyModifiedProperties(); } } }