Files
EmeraidAI/Runtime/Scripts/Components/Required/Editor/EmeraldHealthEditor.cs
T
2025-07-20 10:05:55 +08:00

198 lines
8.7 KiB
C#

using UnityEngine;
using UnityEditor;
using UnityEditorInternal;
namespace EmeraldAI.Utility
{
[CustomEditor(typeof(EmeraldHealth))]
[CanEditMultipleObjects]
public class EmeraldHealthEditor : Editor
{
GUIStyle FoldoutStyle;
Texture HealthEditorIcon;
//Int
SerializedProperty StartingHealthProp, HealRateProp;
//Enum
SerializedProperty UseHitEffectProp;
//Bool
SerializedProperty HideSettingsFoldout, HealthFoldout, HitEffectFoldout, ImmortalProp, AttachHitEffectsProp;
//Float
SerializedProperty HitEffectTimeoutSecondsProp;
//Vector
SerializedProperty HitEffectPosOffsetProp;
ReorderableList HitEffectsList;
void OnEnable()
{
if (HealthEditorIcon == null) HealthEditorIcon = Resources.Load("Editor Icons/EmeraldHealth") as Texture;
InitializeProperties();
InitializeList();
}
void InitializeProperties()
{
//Ints
StartingHealthProp = serializedObject.FindProperty("StartingHealth");
HealRateProp = serializedObject.FindProperty("HealRate");
//Bool
HideSettingsFoldout = serializedObject.FindProperty("HideSettingsFoldout");
HealthFoldout = serializedObject.FindProperty("HealthFoldout");
HitEffectFoldout = serializedObject.FindProperty("HitEffectFoldout");
ImmortalProp = serializedObject.FindProperty("Immortal");
AttachHitEffectsProp = serializedObject.FindProperty("AttachHitEffects");
//Float
HitEffectTimeoutSecondsProp = serializedObject.FindProperty("HitEffectTimeoutSeconds");
//Vector
HitEffectPosOffsetProp = serializedObject.FindProperty("HitEffectPosOffset");
//Enum
UseHitEffectProp = serializedObject.FindProperty("UseHitEffect");
}
void InitializeList ()
{
//Hit Effects List
HitEffectsList = new ReorderableList(serializedObject, serializedObject.FindProperty("HitEffectsList"), true, true, true, true);
HitEffectsList.drawHeaderCallback = rect =>
{
EditorGUI.LabelField(rect, "Hit Effects List", EditorStyles.boldLabel);
};
HitEffectsList.drawElementCallback =
(Rect rect, int index, bool isActive, bool isFocused) =>
{
var element = HitEffectsList.serializedProperty.GetArrayElementAtIndex(index);
EditorGUI.ObjectField(new Rect(rect.x, rect.y, rect.width, EditorGUIUtility.singleLineHeight), element, GUIContent.none);
};
}
public override void OnInspectorGUI()
{
FoldoutStyle = CustomEditorProperties.UpdateEditorStyles();
EmeraldHealth self = (EmeraldHealth)target;
serializedObject.Update();
CustomEditorProperties.BeginScriptHeaderNew("Health", HealthEditorIcon, new GUIContent(), HideSettingsFoldout);
if (!HideSettingsFoldout.boolValue)
{
EditorGUILayout.Space();
HealthSettings(self);
EditorGUILayout.Space();
HitEffectSettings(self);
EditorGUILayout.Space();
}
CustomEditorProperties.EndScriptHeader();
serializedObject.ApplyModifiedProperties();
}
void HealthSettings(EmeraldHealth self)
{
HealthFoldout.boolValue = EditorGUILayout.Foldout(HealthFoldout.boolValue, "Health Settings", true, FoldoutStyle);
if (HealthFoldout.boolValue)
{
CustomEditorProperties.BeginFoldoutWindowBox();
CustomEditorProperties.TextTitleWithDescription("Health Settings", "Controls various health related settings.", true);
EditorGUILayout.PropertyField(ImmortalProp, new GUIContent("Immortal"));
CustomEditorProperties.CustomHelpLabelField("Controls whether or not an AI is immune to damage and is unkillable. If this is enabled, it will disable other settings.", true);
EditorGUI.BeginDisabledGroup(self.Immortal);
CustomEditorProperties.CustomIntField(new Rect(), new GUIContent(), StartingHealthProp, "Starting Health");
CustomEditorProperties.CustomHelpLabelField("Controls how much starting health an AI will have.", true);
CustomEditorProperties.CustomPropertyField(HealRateProp, "Heal Rate", "Controls how much an AI will heal per second when not actively in combat, given their health is below its max.", true);
EditorGUI.EndDisabledGroup();
DrawHealthBar(self);
CustomEditorProperties.EndFoldoutWindowBox();
}
}
void DrawHealthBar (EmeraldHealth self)
{
GUILayout.Space(45);
GUIStyle LabelStyle = new GUIStyle();
LabelStyle.alignment = TextAnchor.MiddleCenter;
LabelStyle.padding.bottom = 4;
LabelStyle.fontStyle = FontStyle.Bold;
LabelStyle.normal.textColor = Color.white;
Rect r = EditorGUILayout.BeginVertical();
GUI.backgroundColor = Color.white;
float CurrentHealth = ((float)self.CurrentHealth / (float)self.StartingHealth);
EditorGUI.DrawRect(new Rect(r.x, r.position.y - 39f, ((r.width)), 32), new Color(0.05f, 0.05f, 0.05f, 0.5f)); //Health Bar BG Outline
EditorGUI.DrawRect(new Rect(r.x + 4, r.position.y - 35f, ((r.width - 8)), 24), new Color(0.16f, 0.16f, 0.16f, 1f)); //Health Bar BG
Color HealthBarColor = Color.Lerp(new Color(0.6f, 0.1f, 0.1f, 1f), new Color(0.15f, 0.42f, 0.15f, 1f), CurrentHealth);
EditorGUI.DrawRect(new Rect(r.x + 4, r.position.y - 35f, ((r.width - 8) * CurrentHealth), 24), HealthBarColor); //Health Bar Main
if (self.CurrentHealth > 0)
{
EditorGUI.LabelField(new Rect(r.x, r.position.y - 35f, (r.width), 26), "Current Health: " + self.CurrentHealth + "/" + self.StartingHealth, LabelStyle);
}
else
{
EditorGUI.LabelField(new Rect(r.x, r.position.y - 35f, (r.width), 26), "Current Health: " + self.CurrentHealth + "/" + self.StartingHealth + " (Dead)", LabelStyle);
}
EditorGUILayout.EndVertical();
if (!Application.isPlaying)
{
self.CurrentHealth = self.StartingHealth;
}
}
void HitEffectSettings(EmeraldHealth self)
{
HitEffectFoldout.boolValue = EditorGUILayout.Foldout(HitEffectFoldout.boolValue, "Hit Effect Settings", true, FoldoutStyle);
if (HitEffectFoldout.boolValue)
{
CustomEditorProperties.BeginFoldoutWindowBox();
CustomEditorProperties.TextTitleWithDescription("Hit Effect Settings", "Allows an AI to display a random hit affect after receiving damage.", true);
EditorGUILayout.PropertyField(UseHitEffectProp, new GUIContent("Use Hit Effect"));
CustomEditorProperties.CustomHelpLabelField("Controls whether or not this AI will use a hit effect when it receives melee damage.", true);
if (self.UseHitEffect == YesOrNo.Yes)
{
CustomEditorProperties.BeginIndent();
CustomEditorProperties.CustomPropertyField(AttachHitEffectsProp, "Attach Hit Effects", "Controls whether or not the Hit Effects will be attached to the AI when it's damaged.", true);
EditorGUILayout.Space();
CustomEditorProperties.CustomHelpLabelField("The hit effect that will appear when this AI receives damage.", true);
HitEffectsList.DoLayoutList();
EditorGUILayout.Space();
EditorGUILayout.Space();
EditorGUILayout.PropertyField(HitEffectTimeoutSecondsProp, new GUIContent("Hit Effect Timeout Seconds"));
CustomEditorProperties.CustomHelpLabelField("Controls how long the hit effect will be visible before being deactivated.", true);
EditorGUILayout.Space();
EditorGUILayout.PropertyField(HitEffectPosOffsetProp, new GUIContent("Hit Effect Position Offset"));
CustomEditorProperties.CustomHelpLabelField("Controls the offset position of the hit effect using the AI's Hit Transform position.", true);
EditorGUILayout.Space();
CustomEditorProperties.EndIndent();
}
CustomEditorProperties.EndFoldoutWindowBox();
}
}
}
}