using Minigames.Airplane.Core.Spawning; using Minigames.Airplane.Data; using UnityEditor; using UnityEngine; namespace Editor.Minigames.Airplane { /// /// Custom editor for ParallaxBackgroundSpawner. /// Enforces exactly 3 pools with custom labels (Background/Middle/Foreground). /// Prevents array manipulation and provides clean, designer-friendly interface. /// [CustomEditor(typeof(ParallaxBackgroundSpawner))] public class ParallaxBackgroundSpawnerEditor : UnityEditor.Editor { private SerializedProperty _poolsProperty; private SerializedProperty _backgroundSortLayerProperty; private SerializedProperty _middleSortLayerProperty; private SerializedProperty _foregroundSortLayerProperty; private SerializedProperty _cameraManagerProperty; private SerializedProperty _showDebugLogsProperty; private readonly string[] _layerNames = { "Background Layer", "Middle Layer", "Foreground Layer" }; private readonly string[] _layerDescriptions = { "Slowest parallax - furthest back", "Medium parallax - middle depth", "Fastest parallax - closest to camera" }; private bool[] _poolFoldouts = new bool[3]; private void OnEnable() { _poolsProperty = serializedObject.FindProperty("pools"); _backgroundSortLayerProperty = serializedObject.FindProperty("backgroundSortLayer"); _middleSortLayerProperty = serializedObject.FindProperty("middleSortLayer"); _foregroundSortLayerProperty = serializedObject.FindProperty("foregroundSortLayer"); _cameraManagerProperty = serializedObject.FindProperty("cameraManager"); _showDebugLogsProperty = serializedObject.FindProperty("showDebugLogs"); // Ensure exactly 3 pools exist EnsureThreePools(); } private void EnsureThreePools() { if (_poolsProperty.arraySize != 3) { _poolsProperty.arraySize = 3; // Initialize pool descriptions for (int i = 0; i < 3; i++) { var poolElement = _poolsProperty.GetArrayElementAtIndex(i); var descProperty = poolElement.FindPropertyRelative("description"); if (string.IsNullOrEmpty(descProperty.stringValue)) { descProperty.stringValue = _layerNames[i]; } } serializedObject.ApplyModifiedProperties(); } } public override void OnInspectorGUI() { serializedObject.Update(); EditorGUILayout.HelpBox("Note: Spawn distances, recency tracking, and debug settings are configured globally in AirplaneSettings. Containers are configured in AirplaneSpawnManager.", MessageType.Info); EditorGUILayout.Space(); // Camera Integration EditorGUILayout.PropertyField(_cameraManagerProperty); EditorGUILayout.Space(); // Sort Layers EditorGUILayout.LabelField("Sort Layer Configuration", EditorStyles.boldLabel); EditorGUILayout.PropertyField(_backgroundSortLayerProperty, new GUIContent("Background Sort Layer")); EditorGUILayout.PropertyField(_middleSortLayerProperty, new GUIContent("Middle Sort Layer")); EditorGUILayout.PropertyField(_foregroundSortLayerProperty, new GUIContent("Foreground Sort Layer")); EditorGUILayout.Space(); // Pool Mode (locked to Exclusive) EditorGUILayout.LabelField("Spawn Mode", EditorStyles.boldLabel); EditorGUI.BeginDisabledGroup(true); EditorGUILayout.TextField("Pool Mode", "Exclusive (Fixed)"); EditorGUI.EndDisabledGroup(); EditorGUILayout.HelpBox("Parallax spawner always uses Exclusive mode - each layer spawns independently", MessageType.Info); EditorGUILayout.Space(); // Parallax Layers (exactly 3, custom display) EditorGUILayout.LabelField("Parallax Layers (Fixed: 3 layers)", EditorStyles.boldLabel); EnsureThreePools(); // Safety check for (int i = 0; i < 3; i++) { var poolElement = _poolsProperty.GetArrayElementAtIndex(i); var prefabsProperty = poolElement.FindPropertyRelative("prefabs"); var unlockTimeProperty = poolElement.FindPropertyRelative("unlockTime"); var descProperty = poolElement.FindPropertyRelative("description"); EditorGUILayout.BeginVertical(EditorStyles.helpBox); // Foldout with custom label _poolFoldouts[i] = EditorGUILayout.Foldout(_poolFoldouts[i], $"{_layerNames[i]} (Pool {i})", true, EditorStyles.foldoutHeader); if (_poolFoldouts[i]) { EditorGUI.indentLevel++; EditorGUILayout.LabelField(_layerDescriptions[i], EditorStyles.miniLabel); EditorGUILayout.Space(5); EditorGUILayout.PropertyField(prefabsProperty, new GUIContent("Prefabs"), true); EditorGUILayout.PropertyField(unlockTimeProperty, new GUIContent("Unlock Time (seconds)")); // Show info about prefab count if (prefabsProperty.arraySize == 0) { EditorGUILayout.HelpBox("Add prefabs for this layer", MessageType.Warning); } else { EditorGUILayout.LabelField($"Prefabs: {prefabsProperty.arraySize}", EditorStyles.miniLabel); } EditorGUI.indentLevel--; } EditorGUILayout.EndVertical(); EditorGUILayout.Space(5); } EditorGUILayout.Space(); serializedObject.ApplyModifiedProperties(); } } }