#if UNITY_EDITOR
using UnityEngine;
using UnityEditor;
using Colosseum.Enemy;
namespace Colosseum.Editor
{
///
/// BossEnemy 커스텀 인스펙터.
/// 페이즈 정보, HP, 상태를 시각적으로 표시합니다.
///
[CustomEditor(typeof(BossEnemy))]
public class BossEnemyEditor : UnityEditor.Editor
{
private BossEnemy boss;
private bool showPhaseDetails = true;
private bool showDebugTools = true;
private int selectedPhaseIndex = 0;
private void OnEnable()
{
boss = (BossEnemy)target;
}
public override void OnInspectorGUI()
{
// 기본 인스펙터 그리기
DrawDefaultInspector();
if (!Application.isPlaying)
{
EditorGUILayout.HelpBox("런타임 디버그 정보는 플레이 모드에서만 표시됩니다.", MessageType.Info);
return;
}
EditorGUILayout.Space(10);
// 상태 요약
DrawStatusSummary();
EditorGUILayout.Space(10);
// 페이즈 정보
DrawPhaseInfo();
EditorGUILayout.Space(10);
// 디버그 도구
DrawDebugTools();
}
///
/// 상태 요약 표시
///
private void DrawStatusSummary()
{
EditorGUILayout.LabelField("상태 요약", EditorStyles.boldLabel);
EditorGUI.indentLevel++;
// HP 바
float hpPercent = boss.MaxHealth > 0 ? boss.CurrentHealth / boss.MaxHealth : 0f;
DrawProgressBar("HP", hpPercent, GetHealthColor(hpPercent), $"{boss.CurrentHealth:F0} / {boss.MaxHealth:F0}");
// 상태 정보
EditorGUILayout.LabelField("현재 페이즈", $"{boss.CurrentPhaseIndex + 1} / {boss.TotalPhases}");
EditorGUILayout.LabelField("상태", GetStatusText());
if (boss.CurrentPhase != null)
{
EditorGUILayout.LabelField("페이즈명", boss.CurrentPhase.PhaseName);
}
EditorGUI.indentLevel--;
}
///
/// 페이즈 상세 정보 표시
///
private void DrawPhaseInfo()
{
showPhaseDetails = EditorGUILayout.Foldout(showPhaseDetails, "페이즈 상세 정보", true);
if (!showPhaseDetails)
return;
EditorGUI.indentLevel++;
var phasesProp = serializedObject.FindProperty("phases");
if (phasesProp == null || phasesProp.arraySize == 0)
{
EditorGUILayout.HelpBox("등록된 페이즈가 없습니다.", MessageType.Warning);
EditorGUI.indentLevel--;
return;
}
for (int i = 0; i < phasesProp.arraySize; i++)
{
var phaseProp = phasesProp.GetArrayElementAtIndex(i);
var phase = phaseProp.objectReferenceValue as BossPhaseData;
if (phase == null)
continue;
bool isCurrentPhase = i == boss.CurrentPhaseIndex;
bool isCompleted = i < boss.CurrentPhaseIndex;
// 페이즈 헤더
GUIStyle phaseStyle = new GUIStyle(EditorStyles.foldout);
if (isCurrentPhase)
phaseStyle.fontStyle = FontStyle.Bold;
EditorGUILayout.BeginHorizontal();
// 상태 아이콘
string statusIcon = isCurrentPhase ? "▶" : (isCompleted ? "✓" : "○");
GUIContent phaseLabel = new GUIContent($"{statusIcon} Phase {i + 1}: {phase.PhaseName}");
EditorGUILayout.LabelField(phaseLabel, GUILayout.Width(200));
// 전환 조건
EditorGUILayout.LabelField($"[{phase.TransitionType}]", EditorStyles.miniLabel, GUILayout.Width(100));
EditorGUILayout.EndHorizontal();
if (isCurrentPhase)
{
EditorGUI.indentLevel++;
EditorGUILayout.LabelField($"전환 조건: {GetTransitionConditionText(phase)}");
EditorGUILayout.LabelField($"경과 시간: {boss.PhaseElapsedTime:F1}초");
EditorGUI.indentLevel--;
}
EditorGUILayout.Space(2);
}
EditorGUI.indentLevel--;
}
///
/// 디버그 도구 표시
///
private void DrawDebugTools()
{
showDebugTools = EditorGUILayout.Foldout(showDebugTools, "디버그 도구", true);
if (!showDebugTools)
return;
EditorGUI.indentLevel++;
EditorGUILayout.HelpBox("이 도구는 서버에서만 작동합니다.", MessageType.Info);
// 페이즈 강제 전환
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField("페이즈 강제 전환", GUILayout.Width(120));
selectedPhaseIndex = EditorGUILayout.IntSlider(selectedPhaseIndex, 0, Mathf.Max(0, boss.TotalPhases - 1));
if (GUILayout.Button("전환", GUILayout.Width(60)))
{
if (Application.isPlaying)
{
boss.ForcePhaseTransition(selectedPhaseIndex);
}
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.Space(5);
// 현재 페이즈 재시작
if (GUILayout.Button("현재 페이즈 재시작"))
{
if (Application.isPlaying)
{
boss.RestartCurrentPhase();
}
}
EditorGUILayout.Space(5);
// HP 조작
EditorGUILayout.LabelField("HP 조작", EditorStyles.boldLabel);
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button("HP 10%"))
{
SetBossHP(0.1f);
}
if (GUILayout.Button("HP 30%"))
{
SetBossHP(0.3f);
}
if (GUILayout.Button("HP 50%"))
{
SetBossHP(0.5f);
}
if (GUILayout.Button("HP 100%"))
{
SetBossHP(1f);
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.Space(5);
// 커스텀 조건
EditorGUILayout.LabelField("커스텀 조건 설정", EditorStyles.boldLabel);
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField("조건 ID:", GUILayout.Width(60));
string conditionId = EditorGUILayout.TextField("Enraged");
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button("활성화"))
{
boss.SetCustomCondition(conditionId, true);
}
if (GUILayout.Button("비활성화"))
{
boss.SetCustomCondition(conditionId, false);
}
EditorGUILayout.EndHorizontal();
EditorGUI.indentLevel--;
}
///
/// HP 설정 (서버에서만)
///
private void SetBossHP(float percent)
{
if (!Application.isPlaying)
return;
float targetHP = boss.MaxHealth * percent;
float damage = boss.CurrentHealth - targetHP;
if (damage > 0)
{
boss.TakeDamage(damage);
}
else if (damage < 0)
{
boss.Heal(-damage);
}
}
///
/// 진행 바 그리기
///
private void DrawProgressBar(string label, float value, Color color, string text = "")
{
Rect rect = EditorGUILayout.GetControlRect();
rect.height = 20f;
// 레이블
Rect labelRect = new Rect(rect.x, rect.y, 60, rect.height);
EditorGUI.LabelField(labelRect, label);
// 바
Rect barRect = new Rect(rect.x + 65, rect.y, rect.width - 65, rect.height);
EditorGUI.DrawRect(barRect, new Color(0.2f, 0.2f, 0.2f));
Rect fillRect = new Rect(barRect.x, barRect.y, barRect.width * Mathf.Clamp01(value), barRect.height);
EditorGUI.DrawRect(fillRect, color);
// 텍스트
if (!string.IsNullOrEmpty(text))
{
GUIStyle centeredStyle = new GUIStyle(EditorStyles.label)
{
alignment = TextAnchor.MiddleCenter
};
EditorGUI.LabelField(barRect, text, centeredStyle);
}
}
///
/// HP 비율에 따른 색상 반환
///
private Color GetHealthColor(float percent)
{
if (percent > 0.6f)
return new Color(0.2f, 0.8f, 0.2f); // 녹색
if (percent > 0.3f)
return new Color(0.9f, 0.7f, 0.1f); // 노란색
return new Color(0.9f, 0.2f, 0.2f); // 빨간색
}
///
/// 상태 텍스트 반환
///
private string GetStatusText()
{
if (boss.IsDead)
return "사망";
if (boss.IsTransitioning)
return "페이즈 전환 중";
return "활성";
}
///
/// 전환 조건 텍스트 반환
///
private string GetTransitionConditionText(BossPhaseData phase)
{
return phase.TransitionType switch
{
PhaseTransitionType.HealthPercent => $"HP ≤ {phase.HealthPercentThreshold * 100:F0}%",
PhaseTransitionType.TimeElapsed => $"시간 ≥ {phase.TimeThreshold:F0}초",
PhaseTransitionType.CustomCondition => $"조건: {phase.CustomConditionId}",
PhaseTransitionType.Manual => "수동 전환",
_ => "알 수 없음"
};
}
}
}
#endif