2025-12-17 18:51:33 +01:00
using Minigames.Airplane.Core.Spawning ;
using Minigames.Airplane.Data ;
using UnityEditor ;
using UnityEngine ;
namespace Editor.Minigames.Airplane
{
/// <summary>
/// Custom editor for ParallaxBackgroundSpawner.
/// Enforces exactly 3 pools with custom labels (Background/Middle/Foreground).
/// Prevents array manipulation and provides clean, designer-friendly interface.
/// </summary>
[CustomEditor(typeof(ParallaxBackgroundSpawner))]
public class ParallaxBackgroundSpawnerEditor : UnityEditor . Editor
{
private SerializedProperty _poolsProperty ;
2025-12-17 22:54:24 +01:00
private SerializedProperty _parallaxSortLayerProperty ;
private SerializedProperty _backgroundSortOrderProperty ;
private SerializedProperty _sortOrderIncrementProperty ;
private SerializedProperty _globalStrengthProperty ;
private SerializedProperty _backgroundSpeedProperty ;
private SerializedProperty _middleSpeedProperty ;
private SerializedProperty _foregroundSpeedProperty ;
2025-12-17 18:51:33 +01:00
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" ) ;
2025-12-17 22:54:24 +01:00
_parallaxSortLayerProperty = serializedObject . FindProperty ( "parallaxSortLayer" ) ;
_backgroundSortOrderProperty = serializedObject . FindProperty ( "backgroundSortOrder" ) ;
_sortOrderIncrementProperty = serializedObject . FindProperty ( "sortOrderIncrement" ) ;
_globalStrengthProperty = serializedObject . FindProperty ( "globalStrength" ) ;
_backgroundSpeedProperty = serializedObject . FindProperty ( "backgroundSpeed" ) ;
_middleSpeedProperty = serializedObject . FindProperty ( "middleSpeed" ) ;
_foregroundSpeedProperty = serializedObject . FindProperty ( "foregroundSpeed" ) ;
2025-12-17 18:51:33 +01:00
_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 ( ) ;
2025-12-17 22:54:24 +01:00
// Parallax Configuration (CENTRALIZED SETTINGS)
EditorGUILayout . LabelField ( "Parallax Configuration" , EditorStyles . boldLabel ) ;
EditorGUILayout . HelpBox ( "These settings apply to ALL parallax elements spawned by this spawner. Adjust speeds to control depth perception." , MessageType . Info ) ;
EditorGUILayout . PropertyField ( _globalStrengthProperty , new GUIContent ( "Global Strength" , "Overall parallax intensity (0 = no effect, 1 = full)" ) ) ;
EditorGUILayout . Space ( 5 ) ;
EditorGUILayout . LabelField ( "Per-Layer Speeds" , EditorStyles . miniBoldLabel ) ;
EditorGUI . indentLevel + + ;
EditorGUILayout . PropertyField ( _backgroundSpeedProperty , new GUIContent ( "Background Speed" , "Slowest layer, appears furthest (e.g., 0.3)" ) ) ;
EditorGUILayout . PropertyField ( _middleSpeedProperty , new GUIContent ( "Middle Speed" , "Medium speed layer (e.g., 0.6)" ) ) ;
EditorGUILayout . PropertyField ( _foregroundSpeedProperty , new GUIContent ( "Foreground Speed" , "Fastest layer, appears closest (e.g., 0.9)" ) ) ;
EditorGUI . indentLevel - - ;
// Validation warnings
if ( _backgroundSpeedProperty . floatValue > = _middleSpeedProperty . floatValue )
{
EditorGUILayout . HelpBox ( "Warning: Background speed should be less than Middle speed for proper depth effect" , MessageType . Warning ) ;
}
if ( _middleSpeedProperty . floatValue > = _foregroundSpeedProperty . floatValue )
{
EditorGUILayout . HelpBox ( "Warning: Middle speed should be less than Foreground speed for proper depth effect" , MessageType . Warning ) ;
}
EditorGUILayout . Space ( ) ;
// Sort Configuration
EditorGUILayout . LabelField ( "Sort Configuration" , EditorStyles . boldLabel ) ;
EditorGUILayout . HelpBox ( "All parallax objects use the same sort layer with different sort orders for depth." , MessageType . Info ) ;
EditorGUILayout . PropertyField ( _parallaxSortLayerProperty , new GUIContent ( "Sort Layer" , "Sort layer for all parallax elements (typically 'Background')" ) ) ;
EditorGUILayout . PropertyField ( _backgroundSortOrderProperty , new GUIContent ( "Background Sort Order" , "Sort order for furthest back layer (e.g., -50)" ) ) ;
EditorGUILayout . PropertyField ( _sortOrderIncrementProperty , new GUIContent ( "Sort Order Increment" , "Increment between layers (e.g., 10 → Middle: -40, Foreground: -30)" ) ) ;
// Show calculated sort orders
int middleOrder = _backgroundSortOrderProperty . intValue + _sortOrderIncrementProperty . intValue ;
int foregroundOrder = _backgroundSortOrderProperty . intValue + ( _sortOrderIncrementProperty . intValue * 2 ) ;
EditorGUILayout . LabelField ( $"Calculated: Background={_backgroundSortOrderProperty.intValue}, Middle={middleOrder}, Foreground={foregroundOrder}" , EditorStyles . miniLabel ) ;
2025-12-17 18:51:33 +01:00
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 descProperty = poolElement . FindPropertyRelative ( "description" ) ;
2025-12-17 22:54:24 +01:00
var overrideMinDistProperty = poolElement . FindPropertyRelative ( "overrideMinDistance" ) ;
var overrideMaxDistProperty = poolElement . FindPropertyRelative ( "overrideMaxDistance" ) ;
2025-12-17 18:51:33 +01:00
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 ) ;
2025-12-17 22:54:24 +01:00
EditorGUILayout . PropertyField ( descProperty , new GUIContent ( "Description" ) ) ;
2025-12-17 18:51:33 +01:00
EditorGUILayout . PropertyField ( prefabsProperty , new GUIContent ( "Prefabs" ) , true ) ;
2025-12-17 22:54:24 +01:00
EditorGUILayout . Space ( 5 ) ;
EditorGUILayout . LabelField ( "Spawn Distance Overrides" , EditorStyles . miniBoldLabel ) ;
EditorGUILayout . HelpBox ( "Leave at 0 to use global settings. Set > 0 to override for this layer." , MessageType . Info ) ;
EditorGUILayout . PropertyField ( overrideMinDistProperty , new GUIContent ( "Min Distance Override" , "Minimum distance between objects (0 = use global)" ) ) ;
EditorGUILayout . PropertyField ( overrideMaxDistProperty , new GUIContent ( "Max Distance Override" , "Maximum distance between objects (0 = use global)" ) ) ;
2025-12-17 18:51:33 +01:00
// 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 ( ) ;
}
}
}