254 lines
9.7 KiB
C#
254 lines
9.7 KiB
C#
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 bvhDepthProp;
|
||
|
||
private bool _savedFog;
|
||
private Color _savedFogColor;
|
||
private FogMode _savedFogMode;
|
||
private float _savedFogStart;
|
||
private float _savedFogEnd;
|
||
private bool _previewActive = false;
|
||
|
||
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");
|
||
bvhDepthProp = serializedObject.FindProperty("BVHPreviewDepth");
|
||
|
||
SaveAndApplyFogPreview();
|
||
EditorApplication.update += OnEditorUpdate;
|
||
}
|
||
|
||
private void OnDisable()
|
||
{
|
||
EditorApplication.update -= OnEditorUpdate;
|
||
RestoreFog();
|
||
}
|
||
|
||
private void OnEditorUpdate()
|
||
{
|
||
if (_previewActive)
|
||
ApplyFogPreview();
|
||
}
|
||
|
||
public override void OnInspectorGUI()
|
||
{
|
||
serializedObject.Update();
|
||
var exporter = (PSXSceneExporter)target;
|
||
|
||
DrawHeader();
|
||
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 DrawHeader()
|
||
{
|
||
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
|
||
? "<color=#88aaff>Room/portal occlusion culling.</color>"
|
||
: "<color=#88cc88>BVH frustum culling.</color>",
|
||
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", true, PSXEditorStyles.FoldoutHeader);
|
||
if (!showFog) return;
|
||
|
||
EditorGUI.indentLevel++;
|
||
|
||
EditorGUILayout.PropertyField(fogEnabledProp, new GUIContent("Enabled"));
|
||
|
||
if (fogEnabledProp.boolValue)
|
||
{
|
||
EditorGUILayout.PropertyField(fogColorProp, new GUIContent("Color"));
|
||
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(
|
||
$"<color=#aaaaaa>Preview: {fogNearUnity:F1} – {fogFarUnity:F1} units | " +
|
||
$"GTE: {8000f / (density * 3f):F0} – {8000f / density:F0} SZ</color>",
|
||
PSXEditorStyles.RichLabel);
|
||
|
||
ApplyFogPreview();
|
||
}
|
||
else
|
||
{
|
||
RenderSettings.fog = false;
|
||
}
|
||
|
||
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<PSXCanvas>() == null)
|
||
{
|
||
EditorGUILayout.LabelField(
|
||
"<color=#ffaa44>Prefab has no PSXCanvas component.</color>",
|
||
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"));
|
||
EditorGUI.indentLevel--;
|
||
}
|
||
|
||
private void DrawSceneStats()
|
||
{
|
||
var exporters = FindObjectsOfType<PSXObjectExporter>();
|
||
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 = FindObjectsOfType<PSXTriggerBox>().Length;
|
||
|
||
EditorGUILayout.BeginVertical(PSXEditorStyles.CardStyle);
|
||
EditorGUILayout.LabelField(
|
||
$"<b>{active}</b>/{total} objects | <b>{staticCol}</b> static <b>{dynamicCol}</b> dynamic <b>{triggerBoxes}</b> triggers",
|
||
PSXEditorStyles.RichLabel);
|
||
EditorGUILayout.EndVertical();
|
||
}
|
||
|
||
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)
|
||
{
|
||
RenderSettings.fog = false;
|
||
return;
|
||
}
|
||
|
||
float gteScale = exporter.GTEScaling;
|
||
int density = Mathf.Clamp(exporter.FogDensity, 1, 10);
|
||
float fogFarSZ = 8000f / density;
|
||
float fogNearSZ = fogFarSZ / 3f;
|
||
|
||
RenderSettings.fog = true;
|
||
RenderSettings.fogColor = exporter.FogColor;
|
||
RenderSettings.fogMode = FogMode.Linear;
|
||
RenderSettings.fogStartDistance = fogNearSZ * gteScale / 4096f;
|
||
RenderSettings.fogEndDistance = fogFarSZ * gteScale / 4096f;
|
||
}
|
||
|
||
private void RestoreFog()
|
||
{
|
||
if (!_previewActive) return;
|
||
_previewActive = false;
|
||
RenderSettings.fog = _savedFog;
|
||
RenderSettings.fogColor = _savedFogColor;
|
||
RenderSettings.fogMode = _savedFogMode;
|
||
RenderSettings.fogStartDistance = _savedFogStart;
|
||
RenderSettings.fogEndDistance = _savedFogEnd;
|
||
}
|
||
}
|
||
}
|