using Minigames.Airplane.Core.Spawning; using Minigames.Airplane.Data; using UnityEditor; using UnityEngine; namespace Editor.Minigames.Airplane { /// /// Custom editor for BaseDistanceSpawner that conditionally shows/hides spawn parameters /// based on the selected SpawnPoolMode. /// [CustomEditor(typeof(BaseDistanceSpawner), true)] public class BaseDistanceSpawnerEditor : UnityEditor.Editor { private SerializedProperty _poolModeProperty; private SerializedProperty _poolsProperty; private SerializedProperty _globalMinDistanceProperty; private SerializedProperty _globalMaxDistanceProperty; private SerializedProperty _recencyPenaltyProperty; private SerializedProperty _groundLayerProperty; private SerializedProperty _maxGroundRaycastProperty; private SerializedProperty _defaultObjectYOffsetProperty; private SerializedProperty _showDebugLogsProperty; protected virtual void OnEnable() { _poolModeProperty = serializedObject.FindProperty("poolMode"); _poolsProperty = serializedObject.FindProperty("pools"); _globalMinDistanceProperty = serializedObject.FindProperty("globalMinDistance"); _globalMaxDistanceProperty = serializedObject.FindProperty("globalMaxDistance"); _recencyPenaltyProperty = serializedObject.FindProperty("recencyPenaltyDuration"); _groundLayerProperty = serializedObject.FindProperty("groundLayer"); _maxGroundRaycastProperty = serializedObject.FindProperty("maxGroundRaycastDistance"); _defaultObjectYOffsetProperty = serializedObject.FindProperty("defaultObjectYOffset"); _showDebugLogsProperty = serializedObject.FindProperty("showDebugLogs"); } public override void OnInspectorGUI() { serializedObject.Update(); EditorGUILayout.LabelField("Distance-Based Spawner", EditorStyles.boldLabel); EditorGUILayout.HelpBox("Spawns objects at calculated X positions based on distance from plane. Containers are configured in AirplaneSpawnManager.", MessageType.Info); EditorGUILayout.Space(); // Pool Configuration EditorGUILayout.LabelField("Pool Configuration", EditorStyles.boldLabel); EditorGUILayout.PropertyField(_poolModeProperty); SpawnPoolMode currentMode = (SpawnPoolMode)_poolModeProperty.enumValueIndex; // Show global parameters only in Together mode if (currentMode == SpawnPoolMode.Together) { EditorGUILayout.Space(); EditorGUILayout.LabelField("Global Spawn Parameters", EditorStyles.boldLabel); EditorGUILayout.PropertyField(_globalMinDistanceProperty); EditorGUILayout.PropertyField(_globalMaxDistanceProperty); EditorGUILayout.HelpBox("Together Mode: All pools use global spawn distances. Per-pool overrides are ignored.", MessageType.Info); } else { EditorGUILayout.HelpBox("Exclusive Mode: Each pool spawns independently. Configure per-pool spawn distances below.", MessageType.Info); } EditorGUILayout.Space(); // Pools array with custom display EditorGUILayout.PropertyField(_poolsProperty, true); // Show per-pool parameter hints if (_poolsProperty.isExpanded && _poolsProperty.arraySize > 0) { EditorGUI.indentLevel++; for (int i = 0; i < _poolsProperty.arraySize; i++) { var poolProperty = _poolsProperty.GetArrayElementAtIndex(i); var overrideMinProperty = poolProperty.FindPropertyRelative("overrideMinDistance"); var overrideMaxProperty = poolProperty.FindPropertyRelative("overrideMaxDistance"); if (currentMode == SpawnPoolMode.Together) { // Grey out per-pool overrides in Together mode if (overrideMinProperty.floatValue > 0 || overrideMaxProperty.floatValue > 0) { EditorGUILayout.HelpBox($"Pool {i}: Per-pool overrides ignored in Together mode", MessageType.Warning); } } else { // Show active overrides in Exclusive mode if (overrideMinProperty.floatValue <= 0 && overrideMaxProperty.floatValue <= 0) { EditorGUILayout.HelpBox($"Pool {i}: Using global distances (set overrides > 0 to customize)", MessageType.Info); } } } EditorGUI.indentLevel--; } EditorGUILayout.Space(); // Object Positioning EditorGUILayout.LabelField("Object Positioning", EditorStyles.boldLabel); EditorGUILayout.PropertyField(_groundLayerProperty); EditorGUILayout.PropertyField(_maxGroundRaycastProperty); EditorGUILayout.PropertyField(_defaultObjectYOffsetProperty); EditorGUILayout.HelpBox("Prefabs can use PrefabSpawnEntryComponent to specify Y positioning: SnapToGround, SpecifiedY, or RandomRange", MessageType.Info); EditorGUILayout.Space(); // Recency Tracking EditorGUILayout.LabelField("Recency Tracking", EditorStyles.boldLabel); EditorGUILayout.PropertyField(_recencyPenaltyProperty); EditorGUILayout.HelpBox("Recently spawned prefabs receive lower weight for diversity", MessageType.Info); EditorGUILayout.Space(); // Debug EditorGUILayout.LabelField("Debug", EditorStyles.boldLabel); EditorGUILayout.PropertyField(_showDebugLogsProperty); serializedObject.ApplyModifiedProperties(); } } }