using Minigames.Airplane.Core.Spawning; using Minigames.Airplane.Data; using UnityEditor; using UnityEngine; namespace Editor.Minigames.Airplane { /// /// Custom editor for ObstacleDistanceSpawner. /// Enforces exactly 2 pools (Positive/Negative) with custom labels. /// All spawn parameters configured in AirplaneSettings. /// [CustomEditor(typeof(ObstacleDistanceSpawner))] public class ObstacleDistanceSpawnerEditor : UnityEditor.Editor { private SerializedProperty _poolModeProperty; private SerializedProperty _poolsProperty; private readonly string[] _poolNames = { "Positive Obstacles", "Negative Obstacles" }; private readonly string[] _poolDescriptions = { "Obstacles that benefit the player", "Obstacles that hinder the player" }; private bool[] _poolFoldouts = new bool[2]; private void OnEnable() { _poolModeProperty = serializedObject.FindProperty("poolMode"); _poolsProperty = serializedObject.FindProperty("pools"); // Ensure exactly 2 pools exist EnsureTwoPools(); } private void EnsureTwoPools() { if (_poolsProperty != null && _poolsProperty.arraySize != 2) { _poolsProperty.arraySize = 2; // Initialize pool descriptions for (int i = 0; i < 2; i++) { var poolElement = _poolsProperty.GetArrayElementAtIndex(i); var descProperty = poolElement.FindPropertyRelative("description"); if (descProperty != null && string.IsNullOrEmpty(descProperty.stringValue)) { descProperty.stringValue = _poolNames[i]; } } serializedObject.ApplyModifiedProperties(); } } public override void OnInspectorGUI() { serializedObject.Update(); EditorGUILayout.HelpBox("Note: Positive/Negative ratio, unlock times, spawn distances, recency tracking, positioning, and debug settings are configured globally in AirplaneSettings. Containers are configured in AirplaneSpawnManager.", MessageType.Info); EditorGUILayout.Space(); if (_poolModeProperty != null) { EditorGUILayout.PropertyField(_poolModeProperty); SpawnPoolMode currentMode = (SpawnPoolMode)_poolModeProperty.enumValueIndex; if (currentMode == SpawnPoolMode.Together) { EditorGUILayout.HelpBox("Together Mode: Both pools share a single spawn stream using global distances from settings.", MessageType.Info); } else { EditorGUILayout.HelpBox("Exclusive Mode: Each pool spawns independently. Use per-pool overrides or global distances from settings.", MessageType.Info); } } EditorGUILayout.Space(); // Obstacle Pools (exactly 2, custom display) EditorGUILayout.LabelField("Obstacle Pools (Fixed: 2 pools)", EditorStyles.boldLabel); EnsureTwoPools(); if (_poolsProperty != null && _poolsProperty.arraySize == 2) { for (int i = 0; i < 2; i++) { var poolElement = _poolsProperty.GetArrayElementAtIndex(i); var prefabsProperty = poolElement.FindPropertyRelative("prefabs"); var descriptionProperty = poolElement.FindPropertyRelative("description"); EditorGUILayout.BeginVertical(EditorStyles.helpBox); // Foldout with custom label _poolFoldouts[i] = EditorGUILayout.Foldout(_poolFoldouts[i], $"{_poolNames[i]} (Pool {i})", true, EditorStyles.foldoutHeader); if (_poolFoldouts[i]) { EditorGUI.indentLevel++; EditorGUILayout.LabelField(_poolDescriptions[i], EditorStyles.miniLabel); EditorGUILayout.Space(5); if (prefabsProperty != null) { EditorGUILayout.PropertyField(prefabsProperty, new GUIContent("Prefabs"), true); } if (descriptionProperty != null) { EditorGUILayout.PropertyField(descriptionProperty, new GUIContent("Description")); } // Show info about prefab count if (prefabsProperty != null) { if (prefabsProperty.arraySize == 0) { EditorGUILayout.HelpBox("Add prefabs for this pool", MessageType.Warning); } else { EditorGUILayout.LabelField($"Prefabs: {prefabsProperty.arraySize}", EditorStyles.miniLabel); } } EditorGUI.indentLevel--; } EditorGUILayout.EndVertical(); EditorGUILayout.Space(5); } } EditorGUILayout.Space(); EditorGUILayout.HelpBox("Note: Positive/Negative ratio, unlock times, spawn distances, recency tracking, positioning, and debug settings are configured globally in AirplaneSettings. Containers are configured in AirplaneSpawnManager.", MessageType.Info); serializedObject.ApplyModifiedProperties(); } } }