init 1.1.2
This commit is contained in:
@@ -0,0 +1,130 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
namespace EmeraldAI.Utility
|
||||
{
|
||||
[CustomEditor(typeof(EmeraldDebugger))]
|
||||
[CanEditMultipleObjects]
|
||||
public class EmeraldDebuggerEditor : Editor
|
||||
{
|
||||
GUIStyle FoldoutStyle;
|
||||
Texture EventsEditorIcon;
|
||||
|
||||
//Bools
|
||||
SerializedProperty SettingsFoldoutProp, HideSettingsFoldoutProp;
|
||||
|
||||
SerializedProperty EnableDebuggingToolsProp, DrawLineOfSightLinesProp, DrawNavMeshPathProp, DrawNavMeshDestinationProp, DrawLookAtPointsProp, DrawUndetectedTargetsLineProp, DebugLogTargetsProp, DebugLogObstructionsProp, NavMeshPathColorProp, NavMeshDestinationColorProp,
|
||||
DrawFootstepPositions, DebugLogFootsteps;
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
if (EventsEditorIcon == null) EventsEditorIcon = Resources.Load("Editor Icons/EmeraldDebugger") as Texture;
|
||||
InitializeProperties();
|
||||
}
|
||||
|
||||
void InitializeProperties()
|
||||
{
|
||||
//Bool
|
||||
SettingsFoldoutProp = serializedObject.FindProperty("SettingsFoldout");
|
||||
HideSettingsFoldoutProp = serializedObject.FindProperty("HideSettingsFoldout");
|
||||
|
||||
EnableDebuggingToolsProp = serializedObject.FindProperty("EnableDebuggingTools");
|
||||
DrawLineOfSightLinesProp = serializedObject.FindProperty("DrawLineOfSightLines");
|
||||
DrawNavMeshPathProp = serializedObject.FindProperty("DrawNavMeshPath");
|
||||
DrawNavMeshDestinationProp = serializedObject.FindProperty("DrawNavMeshDestination");
|
||||
DrawLookAtPointsProp = serializedObject.FindProperty("DrawLookAtPoints");
|
||||
DrawUndetectedTargetsLineProp = serializedObject.FindProperty("DrawUndetectedTargetsLine");
|
||||
DebugLogTargetsProp = serializedObject.FindProperty("DebugLogTargets");
|
||||
DebugLogObstructionsProp = serializedObject.FindProperty("DebugLogObstructions");
|
||||
NavMeshPathColorProp = serializedObject.FindProperty("NavMeshPathColor");
|
||||
NavMeshDestinationColorProp = serializedObject.FindProperty("NavMeshDestinationColor");
|
||||
DrawFootstepPositions = serializedObject.FindProperty("DrawFootstepPositions");
|
||||
DebugLogFootsteps = serializedObject.FindProperty("DebugLogFootsteps");
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
FoldoutStyle = CustomEditorProperties.UpdateEditorStyles();
|
||||
serializedObject.Update();
|
||||
|
||||
CustomEditorProperties.BeginScriptHeaderNew("Debugger", EventsEditorIcon, new GUIContent(), HideSettingsFoldoutProp);
|
||||
|
||||
if (!HideSettingsFoldoutProp.boolValue)
|
||||
{
|
||||
EditorGUILayout.Space();
|
||||
GeneralEvents();
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
|
||||
CustomEditorProperties.EndScriptHeader();
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
|
||||
void GeneralEvents()
|
||||
{
|
||||
EmeraldDebugger self = (EmeraldDebugger)target;
|
||||
|
||||
SettingsFoldoutProp.boolValue = EditorGUILayout.Foldout(SettingsFoldoutProp.boolValue, "Debugging Settings", true, FoldoutStyle);
|
||||
|
||||
if (SettingsFoldoutProp.boolValue)
|
||||
{
|
||||
CustomEditorProperties.BeginFoldoutWindowBox();
|
||||
CustomEditorProperties.TextTitleWithDescription("Debugging Settings", "Allows users to see lots of internal functionality and useful information to help identify issues or bugs. Control which debugging settings will be enabled. " +
|
||||
"You can use the Enable Debugging Tools setting to disable all options so you can keep this component on AI until it's needed.", true);
|
||||
|
||||
EditorGUILayout.PropertyField(EnableDebuggingToolsProp);
|
||||
CustomEditorProperties.CustomHelpLabelField("Controls whether or not the debugging tools are enabled.", true);
|
||||
|
||||
if (self.EnableDebuggingTools == YesOrNo.Yes)
|
||||
{
|
||||
CustomEditorProperties.BeginIndent(15);
|
||||
EditorGUILayout.PropertyField(DrawLineOfSightLinesProp);
|
||||
CustomEditorProperties.CustomHelpLabelField("Allows Line of Sight raycasts to be draw, while in the Unity Editor. This can be useful for ensuring raycast are being positioned correctly as well as seeing if an AI's sight is being obstructed.", true);
|
||||
|
||||
EditorGUILayout.PropertyField(DrawNavMeshPathProp);
|
||||
CustomEditorProperties.CustomHelpLabelField("Allows an AI's current path to be drawn.", true);
|
||||
if (self.DrawNavMeshPath == YesOrNo.Yes)
|
||||
{
|
||||
CustomEditorProperties.BeginIndent();
|
||||
EditorGUILayout.PropertyField(NavMeshPathColorProp);
|
||||
CustomEditorProperties.CustomHelpLabelField("Controls the color of the NavMesh Path.", true);
|
||||
CustomEditorProperties.EndIndent();
|
||||
}
|
||||
|
||||
EditorGUILayout.PropertyField(DrawNavMeshDestinationProp);
|
||||
CustomEditorProperties.CustomHelpLabelField("Allows an AI's current destination to be drawn. Note: This requires the Emerald Debugger to not be minimized.", true);
|
||||
if (self.DrawNavMeshDestination == YesOrNo.Yes)
|
||||
{
|
||||
CustomEditorProperties.BeginIndent(15);
|
||||
EditorGUILayout.PropertyField(NavMeshDestinationColorProp);
|
||||
CustomEditorProperties.CustomHelpLabelField("Controls the color of the NavMesh Destination.", true);
|
||||
CustomEditorProperties.EndIndent();
|
||||
}
|
||||
|
||||
EditorGUILayout.PropertyField(DrawLookAtPointsProp);
|
||||
CustomEditorProperties.CustomHelpLabelField("Allows the AI's current look at point to be draw (when using the InverseK inematics component). " +
|
||||
"This can be useful to ensuring AI are looking at the right points of a target, including positions that are modified with a Target Position Modifier component.", true);
|
||||
|
||||
EditorGUILayout.PropertyField(DrawUndetectedTargetsLineProp);
|
||||
CustomEditorProperties.CustomHelpLabelField("Allows targets within an AI's detection radius, that haven't been detected yet, to have a line drawn to them. This can happen if an undetected target is still obstructed or is outside of an AI's Field of View.", true);
|
||||
|
||||
EditorGUILayout.PropertyField(DebugLogObstructionsProp);
|
||||
CustomEditorProperties.CustomHelpLabelField("Allows the AI's obstructions to be displayed in the Unity Console. This can be useful for identifying the AI's current obstruction between it and its target.", true);
|
||||
|
||||
EditorGUILayout.PropertyField(DebugLogTargetsProp);
|
||||
CustomEditorProperties.CustomHelpLabelField("Allows the target objects to be displayed in the Unity Console. This can be useful for ensuring the proper object is being detected when the AI is targeting an object.", true);
|
||||
|
||||
EditorGUILayout.PropertyField(DrawFootstepPositions);
|
||||
CustomEditorProperties.CustomHelpLabelField("Allows the AI's footsteps collision positions to be displayed (drawn as yellow circles). If no Footsteps Component is present, this setting will be ignored.", true);
|
||||
|
||||
EditorGUILayout.PropertyField(DebugLogFootsteps);
|
||||
CustomEditorProperties.CustomHelpLabelField("Allows the AI's footsteps collision objects and used Footstep Surface Object to be displayed in the Unity Console. This can be helpful to ensure there are no unintended collisions " +
|
||||
"and that the footstep caculations are detecting properly. If no Footsteps Component is present, this setting will be ignored.", true);
|
||||
CustomEditorProperties.EndIndent();
|
||||
}
|
||||
CustomEditorProperties.EndFoldoutWindowBox();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 295035266ae8e2341a752fe321ec1835
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,172 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using UnityEditorInternal;
|
||||
|
||||
namespace EmeraldAI.Utility
|
||||
{
|
||||
[CustomEditor(typeof(EmeraldEvents))]
|
||||
[CanEditMultipleObjects]
|
||||
public class EmeraldEventsEditor : Editor
|
||||
{
|
||||
GUIStyle FoldoutStyle;
|
||||
Texture EventsEditorIcon;
|
||||
|
||||
//Bools
|
||||
SerializedProperty HideSettingsFoldout, GeneralEventsFoldout, CombatEventsFoldout;
|
||||
|
||||
//Events
|
||||
SerializedProperty OnDeathEventProp, OnTakeDamageEventProp, OnTakeCritDamageEventProp, OnReachedDestinationEventProp, OnReachedWaypointEventProp, OnGeneratedWaypointEventProp, OnStartEventProp, OnAttackStartEventProp, OnFleeEventProp, OnStartCombatEventProp, OnEndCombatEventProp,
|
||||
OnEnabledEventProp, OnPlayerDetectedEventProp, OnKilledTargetEventProp, OnDoDamageEventProp, OnDoCritDamageEventProp, OnAttackEndEventProp, OnEnemyTargetDetectedEventProp;
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
if (EventsEditorIcon == null) EventsEditorIcon = Resources.Load("Editor Icons/EmeraldEvents") as Texture;
|
||||
InitializeProperties();
|
||||
}
|
||||
|
||||
void InitializeProperties()
|
||||
{
|
||||
//Bools
|
||||
HideSettingsFoldout = serializedObject.FindProperty("HideSettingsFoldout");
|
||||
GeneralEventsFoldout = serializedObject.FindProperty("GeneralEventsFoldout");
|
||||
CombatEventsFoldout = serializedObject.FindProperty("CombatEventsFoldout");
|
||||
|
||||
//Events
|
||||
OnDeathEventProp = serializedObject.FindProperty("OnDeathEvent");
|
||||
OnTakeDamageEventProp = serializedObject.FindProperty("OnTakeDamageEvent");
|
||||
OnTakeCritDamageEventProp = serializedObject.FindProperty("OnTakeCritDamageEvent");
|
||||
OnDoDamageEventProp = serializedObject.FindProperty("OnDoDamageEvent");
|
||||
OnReachedDestinationEventProp = serializedObject.FindProperty("OnReachedDestinationEvent");
|
||||
OnReachedWaypointEventProp = serializedObject.FindProperty("OnReachedWaypointEvent");
|
||||
OnGeneratedWaypointEventProp = serializedObject.FindProperty("OnGeneratedWaypointEvent");
|
||||
OnStartEventProp = serializedObject.FindProperty("OnStartEvent");
|
||||
OnPlayerDetectedEventProp = serializedObject.FindProperty("OnPlayerDetectedEvent");
|
||||
OnEnemyTargetDetectedEventProp = serializedObject.FindProperty("OnEnemyTargetDetectedEvent");
|
||||
OnEnabledEventProp = serializedObject.FindProperty("OnEnabledEvent");
|
||||
OnAttackStartEventProp = serializedObject.FindProperty("OnAttackStartEvent");
|
||||
OnAttackEndEventProp = serializedObject.FindProperty("OnAttackEndEvent");
|
||||
OnFleeEventProp = serializedObject.FindProperty("OnFleeEvent");
|
||||
OnStartCombatEventProp = serializedObject.FindProperty("OnStartCombatEvent");
|
||||
OnEndCombatEventProp = serializedObject.FindProperty("OnEndCombatEvent");
|
||||
OnKilledTargetEventProp = serializedObject.FindProperty("OnKilledTargetEvent");
|
||||
OnDoCritDamageEventProp = serializedObject.FindProperty("OnDoCritDamageEvent");
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
FoldoutStyle = CustomEditorProperties.UpdateEditorStyles();
|
||||
EmeraldEvents self = (EmeraldEvents)target;
|
||||
serializedObject.Update();
|
||||
|
||||
CustomEditorProperties.BeginScriptHeaderNew("Events", EventsEditorIcon, new GUIContent(), HideSettingsFoldout);
|
||||
|
||||
if (!HideSettingsFoldout.boolValue)
|
||||
{
|
||||
EditorGUILayout.Space();
|
||||
GeneralEvents(self);
|
||||
EditorGUILayout.Space();
|
||||
CombatEvents(self);
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
|
||||
CustomEditorProperties.EndScriptHeader();
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
|
||||
void GeneralEvents(EmeraldEvents self)
|
||||
{
|
||||
GeneralEventsFoldout.boolValue = EditorGUILayout.Foldout(GeneralEventsFoldout.boolValue, "General Events", true, FoldoutStyle);
|
||||
|
||||
if (GeneralEventsFoldout.boolValue)
|
||||
{
|
||||
CustomEditorProperties.BeginFoldoutWindowBox();
|
||||
CustomEditorProperties.TextTitleWithDescription("General Events", "Holds all general related events.", true);
|
||||
|
||||
CustomEditorProperties.CustomHelpLabelField("Triggers an event when this AI is enabled. This can be useful for events that need to be called when an AI is being respawned.", false);
|
||||
EditorGUILayout.PropertyField(OnEnabledEventProp);
|
||||
|
||||
CustomEditorProperties.CustomHelpLabelField("Triggers an event on Start. This can be useful for initializing custom mechanics and quests as well as spawning animations.", false);
|
||||
EditorGUILayout.PropertyField(OnStartEventProp);
|
||||
|
||||
EditorGUILayout.Space();
|
||||
CustomEditorProperties.CustomHelpLabelField("Triggers an event when this AI reaches their destination when using the Destination Wander Type.", false);
|
||||
EditorGUILayout.PropertyField(OnReachedDestinationEventProp, new GUIContent("On Reached Destination Event"));
|
||||
|
||||
CustomEditorProperties.CustomHelpLabelField("Triggers an event each time this AI arrives at a waypoint (for both Dynamic and Waypoint Wander Types).", false);
|
||||
EditorGUILayout.PropertyField(OnReachedWaypointEventProp, new GUIContent("On Reached Waypoint Event"));
|
||||
|
||||
CustomEditorProperties.CustomHelpLabelField("Triggers an event each time this AI generates a waypoint (for both Dynamic and Waypoint Wander Types).", false);
|
||||
EditorGUILayout.PropertyField(OnGeneratedWaypointEventProp, new GUIContent("On Generated Waypoint Event"));
|
||||
|
||||
EditorGUILayout.Space();
|
||||
CustomEditorProperties.CustomHelpLabelField("Triggers an event when this AI detects the player when not in combat mode. This can be useful for quests, initializing dialogue, or greetings. " +
|
||||
"This event is dependent on the AI's Detection Radius and is triggered when the player enters it.", false);
|
||||
EditorGUILayout.PropertyField(OnPlayerDetectedEventProp);
|
||||
|
||||
CustomEditorProperties.EndFoldoutWindowBox();
|
||||
}
|
||||
}
|
||||
|
||||
void CombatEvents(EmeraldEvents self)
|
||||
{
|
||||
CombatEventsFoldout.boolValue = EditorGUILayout.Foldout(CombatEventsFoldout.boolValue, "Combat Events", true, FoldoutStyle);
|
||||
|
||||
if (CombatEventsFoldout.boolValue)
|
||||
{
|
||||
CustomEditorProperties.BeginFoldoutWindowBox();
|
||||
CustomEditorProperties.TextTitleWithDescription("Combat Events", "Holds all combat related events.", true);
|
||||
|
||||
CustomEditorProperties.CustomHelpLabelField("Triggers an event when the AI first starts combat and will not be called again until the AI re-enters combat.", false);
|
||||
EditorGUILayout.PropertyField(OnStartCombatEventProp);
|
||||
|
||||
CustomEditorProperties.CustomHelpLabelField("Triggers an event when the AI ends combat and there are no detectable enemy targets nearby.", false);
|
||||
EditorGUILayout.PropertyField(OnEndCombatEventProp);
|
||||
|
||||
EditorGUILayout.Space();
|
||||
CustomEditorProperties.CustomHelpLabelField("Triggers an event each time the AI successfully detects a target when while in combat.", false);
|
||||
EditorGUILayout.PropertyField(OnEnemyTargetDetectedEventProp, new GUIContent("On Detect Target Event"));
|
||||
|
||||
EditorGUILayout.Space();
|
||||
CustomEditorProperties.CustomHelpLabelField("Triggers an event when the AI's attack starts. Note: This event will trigger even if the AI misses its target.", false);
|
||||
EditorGUILayout.PropertyField(OnAttackStartEventProp, new GUIContent("On Attack Start Event"));
|
||||
|
||||
EditorGUILayout.Space();
|
||||
CustomEditorProperties.CustomHelpLabelField("Triggers an event when the AI's attack ends. Note: This event will trigger even if the AI misses its target.", false);
|
||||
EditorGUILayout.PropertyField(OnAttackEndEventProp);
|
||||
|
||||
EditorGUILayout.Space();
|
||||
CustomEditorProperties.CustomHelpLabelField("Triggers an event when the AI is damaged.", false);
|
||||
EditorGUILayout.PropertyField(OnTakeDamageEventProp, new GUIContent("On Take Damage Event"));
|
||||
|
||||
EditorGUILayout.Space();
|
||||
CustomEditorProperties.CustomHelpLabelField("Triggers an event when the AI is damaged and takes a critical hit.", false);
|
||||
EditorGUILayout.PropertyField(OnTakeCritDamageEventProp, new GUIContent("On Take Crit Damage Event"));
|
||||
|
||||
EditorGUILayout.Space();
|
||||
CustomEditorProperties.CustomHelpLabelField("Triggers an event when the AI successfully deals any kind of damage.", false);
|
||||
EditorGUILayout.PropertyField(OnDoDamageEventProp);
|
||||
|
||||
EditorGUILayout.Space();
|
||||
CustomEditorProperties.CustomHelpLabelField("Triggers an event when the AI deals damage and it's a critical hit.", false);
|
||||
EditorGUILayout.PropertyField(OnDoCritDamageEventProp);
|
||||
|
||||
EditorGUILayout.Space();
|
||||
CustomEditorProperties.CustomHelpLabelField("Triggers an event when the AI flees. This can be useful for fleeing sounds or other added functionality.", false);
|
||||
EditorGUILayout.PropertyField(OnFleeEventProp);
|
||||
|
||||
EditorGUILayout.Space();
|
||||
CustomEditorProperties.CustomHelpLabelField("Triggers an event when the AI kills a target.", false);
|
||||
EditorGUILayout.PropertyField(OnKilledTargetEventProp);
|
||||
|
||||
EditorGUILayout.Space();
|
||||
CustomEditorProperties.CustomHelpLabelField("Triggers an event when the AI dies. This can be useful for triggering loot generation, quest mechanics, or other death related events.", false);
|
||||
EditorGUILayout.PropertyField(OnDeathEventProp, new GUIContent("On Death Event"));
|
||||
|
||||
CustomEditorProperties.EndFoldoutWindowBox();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d532acd61a9e93241b65e8c68adc9fb3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,169 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using UnityEditorInternal;
|
||||
|
||||
namespace EmeraldAI.Utility
|
||||
{
|
||||
[CustomEditor(typeof(EmeraldFootsteps))]
|
||||
[CanEditMultipleObjects]
|
||||
public class EmeraldFootstepsEditor : Editor
|
||||
{
|
||||
GUIStyle FoldoutStyle;
|
||||
Texture FootstepsEditorIcon;
|
||||
|
||||
//Bools
|
||||
SerializedProperty HideSettingsFoldout, FootstepsFoldout, SurfaceFoldout;
|
||||
|
||||
//Variables
|
||||
SerializedProperty FootstepSurfaces, IgnoreLayers, FeetTransforms;
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
if (FootstepsEditorIcon == null) FootstepsEditorIcon = Resources.Load("Editor Icons/EmeraldFootsteps") as Texture;
|
||||
InitializeProperties();
|
||||
}
|
||||
|
||||
void InitializeProperties()
|
||||
{
|
||||
//Bools
|
||||
HideSettingsFoldout = serializedObject.FindProperty("HideSettingsFoldout");
|
||||
FootstepsFoldout = serializedObject.FindProperty("FootstepsFoldout");
|
||||
SurfaceFoldout = serializedObject.FindProperty("SurfaceFoldout");
|
||||
|
||||
//Variables
|
||||
FootstepSurfaces = serializedObject.FindProperty("FootstepSurfaces");
|
||||
IgnoreLayers = serializedObject.FindProperty("IgnoreLayers");
|
||||
FeetTransforms = serializedObject.FindProperty("FeetTransforms");
|
||||
}
|
||||
|
||||
void DisplayWarningMessages (EmeraldFootsteps self)
|
||||
{
|
||||
if (self.FeetTransforms.Count == 0)
|
||||
{
|
||||
CustomEditorProperties.DisplaySetupWarning("The Feet Transforms list is empty, please assign your AI's feet transforms to Feet Transforms list.");
|
||||
}
|
||||
else if (self.FootstepSurfaces.Count == 0)
|
||||
{
|
||||
CustomEditorProperties.DisplaySetupWarning("The Footstep Surfaces list is empty, please assign at least 1 Footstep Surface Object.");
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
FoldoutStyle = CustomEditorProperties.UpdateEditorStyles();
|
||||
EmeraldFootsteps self = (EmeraldFootsteps)target;
|
||||
serializedObject.Update();
|
||||
|
||||
CustomEditorProperties.BeginScriptHeaderNew("Footsteps", FootstepsEditorIcon, new GUIContent(), HideSettingsFoldout);
|
||||
|
||||
DisplayWarningMessages(self);
|
||||
|
||||
if (!HideSettingsFoldout.boolValue)
|
||||
{
|
||||
EditorGUILayout.Space();
|
||||
FootstepSettings(self);
|
||||
EditorGUILayout.Space();
|
||||
SurfaceSettings(self);
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
|
||||
CustomEditorProperties.EndScriptHeader();
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
|
||||
void FootstepSettings(EmeraldFootsteps self)
|
||||
{
|
||||
FootstepsFoldout.boolValue = EditorGUILayout.Foldout(FootstepsFoldout.boolValue, "Footstep Settings", true, FoldoutStyle);
|
||||
|
||||
if (FootstepsFoldout.boolValue)
|
||||
{
|
||||
CustomEditorProperties.BeginFoldoutWindowBox();
|
||||
CustomEditorProperties.TextTitleWithDescription("Foostep Settings", "Controls various settings for the Foosteps component.", false);
|
||||
CustomEditorProperties.ImportantTutorialButton("You will need to create Footstep Animation Events on your AI's animations in order for footsteps to trigger.", "https://black-horizon-studios.gitbook.io/emerald-ai-wiki/emerald-components-optional/footsteps-component/setting-up-the-footsteps-component");
|
||||
EditorGUILayout.Space();
|
||||
|
||||
CustomEditorProperties.CustomPropertyField(IgnoreLayers, "Ignore Layers", "Controls which layers will be ignored when calculating footsteps. Your AI's own layer and its LBD's Collider Layer will automatically be included during runtime.", true);
|
||||
EditorGUILayout.Space();
|
||||
|
||||
if (GUILayout.Button(new GUIContent("Auto Grab Feet Transforms", "Attemps to automatically grab the AI's feet transforms.")))
|
||||
{
|
||||
GetFeetTransforms(self);
|
||||
}
|
||||
|
||||
EditorGUILayout.Space();
|
||||
CustomEditorProperties.BeginIndent(12);
|
||||
CustomEditorProperties.CustomHelpLabelField("Controls the transforms for this AI's feet. Raycasts will be fired from these points to calculate footsteps. If Step Effects are used, they will be spawned at the position of the foot closest to the ground.", false);
|
||||
EditorGUILayout.PropertyField(FeetTransforms);
|
||||
CustomEditorProperties.EndIndent();
|
||||
EditorGUILayout.Space();
|
||||
|
||||
CustomEditorProperties.EndFoldoutWindowBox();
|
||||
}
|
||||
}
|
||||
|
||||
void SurfaceSettings(EmeraldFootsteps self)
|
||||
{
|
||||
SurfaceFoldout.boolValue = EditorGUILayout.Foldout(SurfaceFoldout.boolValue, "Surface Settings", true, FoldoutStyle);
|
||||
|
||||
if (SurfaceFoldout.boolValue)
|
||||
{
|
||||
CustomEditorProperties.BeginFoldoutWindowBox();
|
||||
CustomEditorProperties.TextTitleWithDescription("Surface Settings", "Controls the Footstep Surface Objects that will be used. A Footstep Surface Object can be created by right clicking in the Project tab and going to Create>Emerald AI>Footstep Surface Object.", true);
|
||||
|
||||
CustomEditorProperties.CustomHelpLabelField("A list of Footstep Surfaces used to determine which footstep sound and effect should play given the received information.", false);
|
||||
CustomEditorProperties.BeginIndent(12);
|
||||
EditorGUILayout.PropertyField(FootstepSurfaces);
|
||||
EditorGUILayout.Space();
|
||||
CustomEditorProperties.EndIndent();
|
||||
EditorGUILayout.Space();
|
||||
|
||||
CustomEditorProperties.EndFoldoutWindowBox();
|
||||
}
|
||||
}
|
||||
|
||||
void GetFeetTransforms (EmeraldFootsteps self)
|
||||
{
|
||||
//Search all the transforms within an AI and look for the word root
|
||||
foreach (Transform t in self.GetComponentsInChildren<Transform>())
|
||||
{
|
||||
if (t.name.Contains("foot") || t.name.Contains("Foot") || t.name.Contains("FOOT")) //Look for the word foot within all transforms within the AI
|
||||
{
|
||||
if (!t.name.Contains("ik") && !t.name.Contains("Ik") && !t.name.Contains("IK") && !t.name.Contains("Foot Collider"))
|
||||
{
|
||||
if (!self.FeetTransforms.Contains(t))
|
||||
{
|
||||
self.FeetTransforms.Add(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (Transform root in self.GetComponentsInChildren<Transform>())
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
if (i < root.childCount && root.GetChild(i).name == "root" || i < root.childCount && root.GetChild(i).name == "Root" || i < root.childCount && root.GetChild(i).name == "ROOT") //Only look in the root transform - 3 child index in
|
||||
{
|
||||
foreach (Transform t in root.GetChild(i).GetComponentsInChildren<Transform>())
|
||||
{
|
||||
if (t.name.Contains("foot") || t.name.Contains("Foot") || t.name.Contains("FOOT")) //Look for the word foot within all transforms within the AI
|
||||
{
|
||||
//Exclude transforms with IK, as well as the word Foot Collider, as these aren't usually bone transforms.
|
||||
if (!t.name.Contains("ik") && !t.name.Contains("Ik") && !t.name.Contains("IK") && !t.name.Contains("Foot Collider"))
|
||||
{
|
||||
if (!self.FeetTransforms.Contains(t))
|
||||
{
|
||||
self.FeetTransforms.Add(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c257186aedb9a2e44b877547b14730a9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,193 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using UnityEditorInternal;
|
||||
using System.Linq;
|
||||
using UnityEngine.Animations.Rigging;
|
||||
|
||||
namespace EmeraldAI.Utility
|
||||
{
|
||||
[CustomEditor(typeof(EmeraldInverseKinematics))]
|
||||
[CanEditMultipleObjects]
|
||||
public class EmeraldInverseKinematicsEditor : Editor
|
||||
{
|
||||
GUIStyle FoldoutStyle;
|
||||
Texture InverseKinematicsEditorIcon;
|
||||
|
||||
SerializedProperty WanderingLookAtLimit, WanderingLookSpeed, WanderingLookDistance, WanderingLookHeightOffset, CombatLookAtLimit, CombatLookSpeed, CombatLookDistance, CombatLookHeightOffset;
|
||||
SerializedProperty HideSettingsFoldout, GeneralIKSettingsFoldout, RigSettingsFoldout;
|
||||
ReorderableList UpperBodyRigsList;
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
if (InverseKinematicsEditorIcon == null) InverseKinematicsEditorIcon = Resources.Load("Editor Icons/EmeraldInverseKinematics") as Texture;
|
||||
InitializeProperties();
|
||||
InitializeLists();
|
||||
}
|
||||
|
||||
void InitializeProperties ()
|
||||
{
|
||||
HideSettingsFoldout = serializedObject.FindProperty("HideSettingsFoldout");
|
||||
GeneralIKSettingsFoldout = serializedObject.FindProperty("GeneralIKSettingsFoldout");
|
||||
RigSettingsFoldout = serializedObject.FindProperty("RigSettingsFoldout");
|
||||
|
||||
WanderingLookAtLimit = serializedObject.FindProperty("WanderingLookAtLimit");
|
||||
WanderingLookSpeed = serializedObject.FindProperty("WanderingLookSpeed");
|
||||
WanderingLookDistance = serializedObject.FindProperty("WanderingLookDistance");
|
||||
WanderingLookHeightOffset = serializedObject.FindProperty("WanderingLookHeightOffset");
|
||||
CombatLookAtLimit = serializedObject.FindProperty("CombatLookAtLimit");
|
||||
CombatLookSpeed = serializedObject.FindProperty("CombatLookSpeed");
|
||||
CombatLookDistance = serializedObject.FindProperty("CombatLookDistance");
|
||||
CombatLookHeightOffset = serializedObject.FindProperty("CombatLookHeightOffset");
|
||||
}
|
||||
|
||||
void InitializeLists ()
|
||||
{
|
||||
UpperBodyRigsList = new ReorderableList(serializedObject, serializedObject.FindProperty("UpperBodyRigsList"), true, true, true, true);
|
||||
UpperBodyRigsList.drawHeaderCallback = rect =>
|
||||
{
|
||||
EditorGUI.LabelField(rect, "Upper Body Rigs List", EditorStyles.boldLabel);
|
||||
};
|
||||
UpperBodyRigsList.drawElementCallback =
|
||||
(Rect rect, int index, bool isActive, bool isFocused) =>
|
||||
{
|
||||
var element = UpperBodyRigsList.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();
|
||||
EmeraldInverseKinematics self = (EmeraldInverseKinematics)target;
|
||||
serializedObject.Update();
|
||||
|
||||
CustomEditorProperties.BeginScriptHeaderNew("Inverse Kinematics", InverseKinematicsEditorIcon, new GUIContent(), HideSettingsFoldout);
|
||||
|
||||
MissingRigMessage(self);
|
||||
|
||||
if (!HideSettingsFoldout.boolValue)
|
||||
{
|
||||
EditorGUILayout.Space();
|
||||
RigSettings(self);
|
||||
EditorGUILayout.Space();
|
||||
GeneralIKSettings(self);
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
|
||||
CustomEditorProperties.EndScriptHeader();
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Displays a missing rig message within the EmeraldInverseKinematicsEditor.
|
||||
/// </summary>
|
||||
void MissingRigMessage(EmeraldInverseKinematics self)
|
||||
{
|
||||
if (self.UpperBodyRigsList.Count == 0)
|
||||
{
|
||||
CustomEditorProperties.DisplaySetupWarning("This AI doesn't any applied Rigs so they will not be controlled by this IK component. Please add the Rigs you would like to be controlled to the UpperBodyRigsList within the Rig Settings Foldout.");
|
||||
}
|
||||
}
|
||||
|
||||
void RigSettings(EmeraldInverseKinematics self)
|
||||
{
|
||||
RigSettingsFoldout.boolValue = CustomEditorProperties.Foldout(RigSettingsFoldout.boolValue, "Rig Settings", true, FoldoutStyle);
|
||||
|
||||
if (RigSettingsFoldout.boolValue)
|
||||
{
|
||||
CustomEditorProperties.BeginFoldoutWindowBox();
|
||||
|
||||
CustomEditorProperties.TextTitleWithDescription("Rig Settings", "Assign all Rig components this AI will be using for its IK. Upper Body Rigs will be used for looking and aiming at targets. Lower Body Rigs will be used for positioning an AI's " +
|
||||
"legs and feet with the ground. You will be able to control these settings further with the settings below", true);
|
||||
|
||||
if (GUILayout.Button(new GUIContent("Create New Rig", "Creates a new Rig, in addition to any others that have been created, and automatically assigns and parents it to this AI." +
|
||||
"\n\nNote: You will still need to add a constraint component on a child object within your Rig.")))
|
||||
{
|
||||
CustomRigSetup(self);
|
||||
}
|
||||
|
||||
EditorGUILayout.Space();
|
||||
CustomEditorProperties.CustomHelpLabelField("The Upper Body Rig components (Head, Spine, Chest, Arms, etc.) that this AI uses for its aiming and looking IK.", false);
|
||||
UpperBodyRigsList.DoLayoutList();
|
||||
EditorGUILayout.Space();
|
||||
EditorGUILayout.Space();
|
||||
CustomEditorProperties.EndFoldoutWindowBox();
|
||||
}
|
||||
}
|
||||
|
||||
void CustomRigSetup (EmeraldInverseKinematics self)
|
||||
{
|
||||
var rigBuilder = self.transform.GetComponent<RigBuilder>();
|
||||
|
||||
if (rigBuilder == null)
|
||||
rigBuilder = Undo.AddComponent<RigBuilder>(self.transform.gameObject);
|
||||
else
|
||||
Undo.RecordObject(rigBuilder, "Rig Builder Component Added.");
|
||||
|
||||
var name = "Rig";
|
||||
var cnt = 1;
|
||||
while (rigBuilder.transform.Find(string.Format("{0} {1}", name, cnt)) != null)
|
||||
{
|
||||
cnt++;
|
||||
}
|
||||
name = string.Format("{0} {1}", name, cnt);
|
||||
var rigGameObject = new GameObject(name);
|
||||
Undo.RegisterCreatedObjectUndo(rigGameObject, name);
|
||||
rigGameObject.transform.SetParent(rigBuilder.transform);
|
||||
rigGameObject.transform.localPosition = Vector3.zero;
|
||||
rigGameObject.transform.localScale = Vector3.one;
|
||||
|
||||
var rig = Undo.AddComponent<Rig>(rigGameObject);
|
||||
rigBuilder.layers.Add(new RigLayer(rig));
|
||||
|
||||
if (PrefabUtility.IsPartOfPrefabInstance(rigBuilder))
|
||||
EditorUtility.SetDirty(rigBuilder);
|
||||
|
||||
self.UpperBodyRigsList.Add(rig);
|
||||
}
|
||||
|
||||
void GeneralIKSettings (EmeraldInverseKinematics self)
|
||||
{
|
||||
GeneralIKSettingsFoldout.boolValue = CustomEditorProperties.Foldout(GeneralIKSettingsFoldout.boolValue, "General IK Settings", true, FoldoutStyle);
|
||||
|
||||
if (GeneralIKSettingsFoldout.boolValue)
|
||||
{
|
||||
CustomEditorProperties.BeginFoldoutWindowBox();
|
||||
|
||||
CustomEditorProperties.TextTitleWithDescription("General IK Settings", "Controls the speeds and angles for this AI's IK.", true);
|
||||
|
||||
CustomEditorProperties.CustomIntSlider(new Rect(), new GUIContent(), WanderingLookAtLimit, "Wandering Angle Limit", 1, 90);
|
||||
CustomEditorProperties.CustomHelpLabelField("Controls the angle limit for looking at targets.", true);
|
||||
|
||||
CustomEditorProperties.CustomIntSlider(new Rect(), new GUIContent(), CombatLookAtLimit, "Combat Angle Limit", 1, 90);
|
||||
CustomEditorProperties.CustomHelpLabelField("Controls the angle limit for looking at targets.", true);
|
||||
|
||||
CustomEditorProperties.CustomFloatSlider(new Rect(), new GUIContent(), WanderingLookSpeed, "Wandering Look Speed", 1f, 15f);
|
||||
CustomEditorProperties.CustomHelpLabelField("Controls how quickly an AI will look at targets.", true);
|
||||
|
||||
CustomEditorProperties.CustomFloatSlider(new Rect(), new GUIContent(), CombatLookSpeed, "Combat Look Speed", 1f, 15f);
|
||||
CustomEditorProperties.CustomHelpLabelField("Controls how quickly an AI will look at targets.", true);
|
||||
|
||||
CustomEditorProperties.CustomIntSlider(new Rect(), new GUIContent(), WanderingLookDistance, "Wandering Look Distance", 5, 40);
|
||||
CustomEditorProperties.CustomHelpLabelField("Controls the distance for looking at targets.", true);
|
||||
|
||||
CustomEditorProperties.CustomIntSlider(new Rect(), new GUIContent(), CombatLookDistance, "Combat Look Distance", 5, 40);
|
||||
CustomEditorProperties.CustomHelpLabelField("Controls the distance for looking at targets.", true);
|
||||
|
||||
CustomEditorProperties.CustomFloatSlider(new Rect(), new GUIContent(), WanderingLookHeightOffset, "Wandering Look Height Offset", -3f, 3f);
|
||||
CustomEditorProperties.CustomHelpLabelField("Controls the height offset for the default position when looking at targets.", true);
|
||||
|
||||
CustomEditorProperties.CustomFloatSlider(new Rect(), new GUIContent(), CombatLookHeightOffset, "Combat Look Height Offset", -3f, 3f);
|
||||
CustomEditorProperties.CustomHelpLabelField("Controls the height offset for the default position when looking at targets.", true);
|
||||
|
||||
EditorGUILayout.Space();
|
||||
EditorGUILayout.Space();
|
||||
|
||||
CustomEditorProperties.EndFoldoutWindowBox();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 175906794189e44449125276b4c64b8c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,173 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using UnityEditorInternal;
|
||||
|
||||
namespace EmeraldAI.Utility
|
||||
{
|
||||
[CustomEditor(typeof(EmeraldItems))]
|
||||
[CanEditMultipleObjects]
|
||||
public class EmeraldItemsEditor : Editor
|
||||
{
|
||||
GUIStyle FoldoutStyle;
|
||||
EmeraldCombat EmeraldCombat;
|
||||
Texture ItemsEditorIcon;
|
||||
|
||||
#region SerializedProperties
|
||||
//Bools
|
||||
SerializedProperty HideSettingsFoldout, WeaponsFoldout, ItemsFoldout;
|
||||
|
||||
ReorderableList ItemList, Type1EquippableWeaponsList, Type2EquippableWeaponsList;
|
||||
#endregion
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
EmeraldItems self = (EmeraldItems)target;
|
||||
EmeraldCombat = self.GetComponent<EmeraldCombat>();
|
||||
if (ItemsEditorIcon == null) ItemsEditorIcon = Resources.Load("Editor Icons/EmeraldItems") as Texture;
|
||||
|
||||
InitializeProperties();
|
||||
InitializeLists();
|
||||
}
|
||||
|
||||
void InitializeProperties()
|
||||
{
|
||||
//Bools
|
||||
HideSettingsFoldout = serializedObject.FindProperty("HideSettingsFoldout");
|
||||
WeaponsFoldout = serializedObject.FindProperty("WeaponsFoldout");
|
||||
ItemsFoldout = serializedObject.FindProperty("ItemsFoldout");
|
||||
}
|
||||
|
||||
void InitializeLists()
|
||||
{
|
||||
//Type 1
|
||||
Type1EquippableWeaponsList = DrawEquippableWeaponsList(Type1EquippableWeaponsList, "Type1EquippableWeapons", "Type 1 Equippable Weapons");
|
||||
|
||||
//Type 2
|
||||
Type2EquippableWeaponsList = DrawEquippableWeaponsList(Type2EquippableWeaponsList, "Type2EquippableWeapons", "Type 2 Equippable Weapons");
|
||||
|
||||
//Item Objects
|
||||
ItemList = new ReorderableList(serializedObject, serializedObject.FindProperty("ItemList"), true, true, true, true);
|
||||
ItemList.drawElementCallback =
|
||||
(Rect rect, int index, bool isActive, bool isFocused) =>
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
var element = ItemList.serializedProperty.GetArrayElementAtIndex(index);
|
||||
EditorGUI.PropertyField(new Rect(rect.x + 60, rect.y, rect.width - 120, EditorGUIUtility.singleLineHeight), element.FindPropertyRelative("ItemObject"), GUIContent.none);
|
||||
EditorGUI.PropertyField(new Rect(rect.x, rect.y, 50, EditorGUIUtility.singleLineHeight), element.FindPropertyRelative("ItemID"), GUIContent.none);
|
||||
};
|
||||
|
||||
ItemList.drawHeaderCallback = rect =>
|
||||
{
|
||||
EditorGUI.LabelField(rect, " ID " + " Item Object", EditorStyles.boldLabel);
|
||||
};
|
||||
}
|
||||
|
||||
ReorderableList DrawEquippableWeaponsList(ReorderableList WeaponsList, string WeaponsPropertyName, string WeaponsDisplayName)
|
||||
{
|
||||
WeaponsList = new ReorderableList(serializedObject, serializedObject.FindProperty(WeaponsPropertyName), true, true, true, true);
|
||||
WeaponsList.drawElementCallback =
|
||||
(Rect rect, int index, bool isActive, bool isFocused) =>
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
var element = WeaponsList.serializedProperty.GetArrayElementAtIndex(index);
|
||||
|
||||
EditorGUI.LabelField(new Rect(rect.x + 10, rect.y, rect.width, EditorGUIUtility.singleLineHeight), "Item " + (index + 1).ToString());
|
||||
|
||||
float Height = (EditorGUIUtility.singleLineHeight * 1.25f);
|
||||
|
||||
EditorGUI.LabelField(new Rect(rect.x + 10, rect.y + Height, rect.width, EditorGUIUtility.singleLineHeight), new GUIContent("Held", "The Held object is used to reference the position for spawning droppable weapons and for equipping items.")); //Title
|
||||
EditorGUI.PropertyField(new Rect(rect.x + 100, rect.y + Height, rect.width - 100, EditorGUIUtility.singleLineHeight), element.FindPropertyRelative("HeldObject"), GUIContent.none); //Object
|
||||
|
||||
EditorGUI.PropertyField(new Rect(rect.x - 12.5f, rect.y + Height * 2, rect.width, EditorGUIUtility.singleLineHeight), element.FindPropertyRelative("HolsteredToggle"), GUIContent.none); //Toggle
|
||||
EditorGUI.LabelField(new Rect(rect.x + 10, rect.y + Height * 2, rect.width, EditorGUIUtility.singleLineHeight), new GUIContent("Holstered", "The weapon object that's holstered on an AI. This is used when using Equipping Animations." +
|
||||
"\n\nNote: If an Animation Profile does not have any Equipping Animations, this setting will be ignored.")); //Title
|
||||
EditorGUI.BeginDisabledGroup(!element.FindPropertyRelative("HolsteredToggle").boolValue);
|
||||
EditorGUI.PropertyField(new Rect(rect.x + 100, rect.y + Height * 2, rect.width - 100, EditorGUIUtility.singleLineHeight), element.FindPropertyRelative("HolsteredObject"), GUIContent.none); //Object
|
||||
EditorGUI.EndDisabledGroup();
|
||||
|
||||
EditorGUI.PropertyField(new Rect(rect.x - 12.5f, rect.y + Height * 3, rect.width, EditorGUIUtility.singleLineHeight), element.FindPropertyRelative("DroppableToggle"), GUIContent.none); //Toggle
|
||||
EditorGUI.LabelField(new Rect(rect.x + 10, rect.y + Height * 3, rect.width, EditorGUIUtility.singleLineHeight), new GUIContent("Droppable", "If enabled, this will spawn a copy of the attached object to the exact position and rotation of this item's Held object.")); //Title
|
||||
EditorGUI.BeginDisabledGroup(!element.FindPropertyRelative("DroppableToggle").boolValue);
|
||||
EditorGUI.PropertyField(new Rect(rect.x + 100, rect.y + Height * 3, rect.width - 100, EditorGUIUtility.singleLineHeight), element.FindPropertyRelative("DroppableObject"), GUIContent.none); //Object
|
||||
EditorGUI.EndDisabledGroup();
|
||||
};
|
||||
|
||||
WeaponsList.elementHeightCallback = (int index) =>
|
||||
{
|
||||
SerializedProperty element = WeaponsList.serializedProperty.GetArrayElementAtIndex(index);
|
||||
return EditorGUIUtility.singleLineHeight * 5.0f;
|
||||
};
|
||||
|
||||
WeaponsList.drawHeaderCallback = rect =>
|
||||
{
|
||||
EditorGUI.LabelField(rect, WeaponsDisplayName, EditorStyles.boldLabel);
|
||||
};
|
||||
|
||||
return WeaponsList;
|
||||
}
|
||||
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
FoldoutStyle = CustomEditorProperties.UpdateEditorStyles();
|
||||
EmeraldItems self = (EmeraldItems)target;
|
||||
serializedObject.Update();
|
||||
|
||||
CustomEditorProperties.BeginScriptHeaderNew("Items", ItemsEditorIcon, new GUIContent(), HideSettingsFoldout);
|
||||
|
||||
if (!HideSettingsFoldout.boolValue)
|
||||
{
|
||||
EditorGUILayout.Space();
|
||||
WeaponSettings(self);
|
||||
EditorGUILayout.Space();
|
||||
ItemSettings(self);
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
CustomEditorProperties.EndScriptHeader();
|
||||
}
|
||||
|
||||
void WeaponSettings(EmeraldItems self)
|
||||
{
|
||||
WeaponsFoldout.boolValue = EditorGUILayout.Foldout(WeaponsFoldout.boolValue, "Weapon Settings", true, FoldoutStyle);
|
||||
|
||||
if (WeaponsFoldout.boolValue)
|
||||
{
|
||||
CustomEditorProperties.BeginFoldoutWindowBox();
|
||||
|
||||
CustomEditorProperties.TextTitleWithDescription("Weapon Settings", "Allows AI to enable and disable weapon objects using Animation Events (Requires AI to have Equip and Unequip Animations).", true);
|
||||
|
||||
Type1EquippableWeaponsList.DoLayoutList();
|
||||
|
||||
if (EmeraldCombat.WeaponTypeAmount == EmeraldCombat.WeaponTypeAmounts.Two)
|
||||
{
|
||||
Type2EquippableWeaponsList.DoLayoutList();
|
||||
}
|
||||
|
||||
EditorGUILayout.Space();
|
||||
CustomEditorProperties.EndFoldoutWindowBox();
|
||||
}
|
||||
}
|
||||
|
||||
void ItemSettings(EmeraldItems self)
|
||||
{
|
||||
ItemsFoldout.boolValue = EditorGUILayout.Foldout(ItemsFoldout.boolValue, "Item Settings", true, FoldoutStyle);
|
||||
|
||||
if (ItemsFoldout.boolValue)
|
||||
{
|
||||
CustomEditorProperties.BeginFoldoutWindowBox();
|
||||
|
||||
CustomEditorProperties.TextTitleWithDescription("Item Settings", "Objects that are attached to your AI that can be enabled or disable through Animation Events or programmatically " +
|
||||
"using the item ID. This can be useful for quests items, animation effects, animation specific items, etc. For more information regarding this, please see the Documentation.", true);
|
||||
|
||||
CustomEditorProperties.CustomHelpLabelField("Each Item below has an ID number. This ID is used to find that particular item and to either enable or disable it using Emerald AI's API.", true);
|
||||
ItemList.DoLayoutList();
|
||||
|
||||
CustomEditorProperties.EndFoldoutWindowBox();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cbd9ed11b291eb44f9b611fecce1c014
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,134 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.Linq;
|
||||
using UnityEditorInternal;
|
||||
|
||||
namespace EmeraldAI.Utility
|
||||
{
|
||||
[CustomEditor(typeof(EmeraldOptimization))]
|
||||
[CanEditMultipleObjects]
|
||||
public class EmeraldOptimizationEditor : Editor
|
||||
{
|
||||
GUIStyle FoldoutStyle;
|
||||
Texture OptimizationEditorIcon;
|
||||
|
||||
#region SerializedProperties
|
||||
//Bool
|
||||
SerializedProperty HideSettingsFoldout, OptimizationFoldout;
|
||||
|
||||
//Int
|
||||
SerializedProperty DeactivateDelayProp;
|
||||
|
||||
//Object
|
||||
SerializedProperty AIRendererProp;
|
||||
|
||||
//Enum
|
||||
SerializedProperty OptimizeAIProp, UseDeactivateDelayProp, TotalLODsProp, MeshTypeProp;
|
||||
#endregion
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
if (OptimizationEditorIcon == null) OptimizationEditorIcon = Resources.Load("Editor Icons/EmeraldOptimization") as Texture;
|
||||
|
||||
//Bool
|
||||
HideSettingsFoldout = serializedObject.FindProperty("HideSettingsFoldout");
|
||||
OptimizationFoldout = serializedObject.FindProperty("OptimizationFoldout");
|
||||
|
||||
//Int
|
||||
DeactivateDelayProp = serializedObject.FindProperty("DeactivateDelay");
|
||||
|
||||
//Object
|
||||
AIRendererProp = serializedObject.FindProperty("AIRenderer");
|
||||
|
||||
//Enum
|
||||
OptimizeAIProp = serializedObject.FindProperty("OptimizeAI");
|
||||
UseDeactivateDelayProp = serializedObject.FindProperty("UseDeactivateDelay");
|
||||
TotalLODsProp = serializedObject.FindProperty("TotalLODsRef");
|
||||
MeshTypeProp = serializedObject.FindProperty("MeshType");
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
FoldoutStyle = CustomEditorProperties.UpdateEditorStyles();
|
||||
EmeraldOptimization self = (EmeraldOptimization)target;
|
||||
serializedObject.Update();
|
||||
|
||||
CustomEditorProperties.BeginScriptHeaderNew("Optimization", OptimizationEditorIcon, new GUIContent(), HideSettingsFoldout);
|
||||
|
||||
MissingRendererMessage(self);
|
||||
|
||||
if (!HideSettingsFoldout.boolValue)
|
||||
{
|
||||
EditorGUILayout.Space();
|
||||
OptimizationSettings(self);
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
CustomEditorProperties.EndScriptHeader();
|
||||
}
|
||||
|
||||
void MissingRendererMessage(EmeraldOptimization self)
|
||||
{
|
||||
if (self.OptimizeAI == YesOrNo.Yes && self.MeshType == EmeraldOptimization.MeshTypes.SingleMesh && !self.AIRenderer)
|
||||
{
|
||||
CustomEditorProperties.DisplayWarningMessage("When using the Single Mesh Type, an AI needs to have an assigned Renderer. Please assign your AI's Skinned Mesh Renderer to the AI Renderer slot within the Optimization Settings foldout.");
|
||||
}
|
||||
}
|
||||
|
||||
void OptimizationSettings (EmeraldOptimization self)
|
||||
{
|
||||
OptimizationFoldout.boolValue = EditorGUILayout.Foldout(OptimizationFoldout.boolValue, "Optimization Settings", true, FoldoutStyle);
|
||||
|
||||
if (OptimizationFoldout.boolValue)
|
||||
{
|
||||
CustomEditorProperties.BeginFoldoutWindowBox();
|
||||
|
||||
CustomEditorProperties.TextTitleWithDescription("Optimization Settings", "The optimization component will optimize an AI by disabling certain scripts, functionality, and animations when an AI's model is culled or not visible.", true);
|
||||
|
||||
EditorGUILayout.PropertyField(OptimizeAIProp, new GUIContent("Optimize AI"));
|
||||
CustomEditorProperties.CustomHelpLabelField("Controls whether or not this AI will be optimized when off screen or culled.", true);
|
||||
|
||||
if (self.OptimizeAI == YesOrNo.Yes)
|
||||
{
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
GUILayout.Space(10);
|
||||
EditorGUILayout.BeginVertical();
|
||||
|
||||
EditorGUILayout.PropertyField(UseDeactivateDelayProp, new GUIContent("Use Deactivate Delay"));
|
||||
CustomEditorProperties.CustomHelpLabelField("Controls whether or not there is a delay when using the Disable when Off-Screen feature. If set to No, the AI will be disabled instantly.", true);
|
||||
|
||||
if (self.UseDeactivateDelay == YesOrNo.Yes)
|
||||
{
|
||||
CustomEditorProperties.CustomIntSlider(new Rect(), new GUIContent(), DeactivateDelayProp, "Deactivate Delay", 1, 30);
|
||||
CustomEditorProperties.CustomHelpLabelField("Controls the amount of seconds until the AI will be disabled when either culled or off-screen.", true);
|
||||
}
|
||||
|
||||
CustomEditorProperties.CustomPropertyField(MeshTypeProp, "Mesh Type", "Controls whether this AI uses a single Skinned Mesh Renderer or a LOD Group.", true);
|
||||
|
||||
if (self.MeshType == EmeraldOptimization.MeshTypes.LODGroup)
|
||||
{
|
||||
CustomEditorProperties.DisplayImportantMessage("Info - The LOD Group option requires that an AI has a LOD Group component attached with at least 1 LOD Level. Each level needs to have at least 1 mesh assigned. " +
|
||||
"The Optimization Component will automatically grab all needed information from the LOD Group during Start. Ensure your AI meets these requirements or the Optimization Component will be disabled.");
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
|
||||
if (self.MeshType == EmeraldOptimization.MeshTypes.SingleMesh)
|
||||
{
|
||||
CustomEditorProperties.BeginIndent();
|
||||
EditorGUILayout.PropertyField(AIRendererProp, new GUIContent("AI Main Renderer"));
|
||||
CustomEditorProperties.CustomHelpLabelField("The AI's Main Renderer should be a single Skinned Mesh Renderer an AI uses. If an AI has multiple Skinned Mesh Renderers, an LOD Group should be used instead.", true);
|
||||
CustomEditorProperties.EndIndent();
|
||||
}
|
||||
|
||||
EditorGUILayout.EndVertical();
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
CustomEditorProperties.EndFoldoutWindowBox();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b5f9006483035e445ac1c52e1a814225
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,459 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using UnityEditorInternal;
|
||||
|
||||
namespace EmeraldAI.Utility
|
||||
{
|
||||
[CustomEditor(typeof(EmeraldUI))]
|
||||
[CanEditMultipleObjects]
|
||||
public class EmeraldUIEditor : Editor
|
||||
{
|
||||
GUIStyle FoldoutStyle;
|
||||
Texture UIEditorIcon;
|
||||
|
||||
#region SerializedProperties
|
||||
//Ints
|
||||
SerializedProperty MaxUIScaleSizeProp;
|
||||
|
||||
//Enums
|
||||
SerializedProperty CreateHealthBarsProp, UseCustomFontAINameProp, UseCustomFontAILevelProp, CustomizeHealthBarProp, DisplayAINameProp, DisplayAITitleProp, DisplayAILevelProp, UseAINameUIOutlineEffectProp, UseAILevelUIOutlineEffectProp;
|
||||
|
||||
//Bools
|
||||
SerializedProperty HideSettingsFoldout, UISettingsFoldoutProp, HealthBarsFoldoutProp, CombatTextFoldoutProp, NameTextFoldoutProp, LevelTextFoldoutProp;
|
||||
|
||||
//Layermask
|
||||
SerializedProperty UILayerMaskProp;
|
||||
|
||||
//Float
|
||||
SerializedProperty AINameLineSpacingProp;
|
||||
|
||||
//Colors
|
||||
SerializedProperty HealthBarColorProp, HealthBarColorDamageProp, HealthBarBackgroundColorProp, NameTextColorProp, LevelTextColorProp, AINameUIOutlineColorProp, AILevelUIOutlineColorProp, AINameFontProp, AILevelFontProp;
|
||||
|
||||
//Vectors
|
||||
SerializedProperty AINamePosProp, AILevelPosProp, AINameUIOutlineSizeProp, AILevelUIOutlineSizeProp, HealthBarPosProp, NameTextFontSizeProp, HealthBarScaleProp;
|
||||
|
||||
//Objects
|
||||
SerializedProperty HealthBarImageProp, HealthBarBackgroundImageProp;
|
||||
|
||||
//String
|
||||
SerializedProperty UITagProp, CameraTagProp, AINameProp, AITitleProp, AILevelProp;
|
||||
#endregion
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
if (UIEditorIcon == null) UIEditorIcon = Resources.Load("Editor Icons/EmeraldUI") as Texture;
|
||||
InitializeProperties();
|
||||
}
|
||||
|
||||
void InitializeProperties ()
|
||||
{
|
||||
//Int
|
||||
MaxUIScaleSizeProp = serializedObject.FindProperty("MaxUIScaleSize");
|
||||
|
||||
//Floats
|
||||
AINameLineSpacingProp = serializedObject.FindProperty("AINameLineSpacing");
|
||||
|
||||
//Enums
|
||||
UseAINameUIOutlineEffectProp = serializedObject.FindProperty("UseAINameUIOutlineEffect");
|
||||
UseAILevelUIOutlineEffectProp = serializedObject.FindProperty("UseAILevelUIOutlineEffect");
|
||||
CreateHealthBarsProp = serializedObject.FindProperty("AutoCreateHealthBars");
|
||||
CustomizeHealthBarProp = serializedObject.FindProperty("UseCustomHealthBar");
|
||||
DisplayAINameProp = serializedObject.FindProperty("DisplayAIName");
|
||||
DisplayAITitleProp = serializedObject.FindProperty("DisplayAITitle");
|
||||
DisplayAILevelProp = serializedObject.FindProperty("DisplayAILevel");
|
||||
UseCustomFontAINameProp = serializedObject.FindProperty("UseCustomFontAIName");
|
||||
UseCustomFontAILevelProp = serializedObject.FindProperty("UseCustomFontAILevel");
|
||||
|
||||
//Bools
|
||||
HideSettingsFoldout = serializedObject.FindProperty("HideSettingsFoldout");
|
||||
UISettingsFoldoutProp = serializedObject.FindProperty("UISettingsFoldout");
|
||||
HealthBarsFoldoutProp = serializedObject.FindProperty("HealthBarsFoldout");
|
||||
CombatTextFoldoutProp = serializedObject.FindProperty("CombatTextFoldout");
|
||||
NameTextFoldoutProp = serializedObject.FindProperty("NameTextFoldout");
|
||||
LevelTextFoldoutProp = serializedObject.FindProperty("LevelTextFoldout");
|
||||
|
||||
//Layermask
|
||||
UILayerMaskProp = serializedObject.FindProperty("UILayerMask");
|
||||
|
||||
//Vectors
|
||||
HealthBarPosProp = serializedObject.FindProperty("HealthBarPos");
|
||||
NameTextFontSizeProp = serializedObject.FindProperty("NameTextFontSize");
|
||||
HealthBarScaleProp = serializedObject.FindProperty("HealthBarScale");
|
||||
AINamePosProp = serializedObject.FindProperty("AINamePos");
|
||||
AINameUIOutlineSizeProp = serializedObject.FindProperty("AINameUIOutlineSize");
|
||||
AILevelPosProp = serializedObject.FindProperty("AILevelPos");
|
||||
AILevelUIOutlineSizeProp = serializedObject.FindProperty("AILevelUIOutlineSize");
|
||||
|
||||
//Color
|
||||
HealthBarColorProp = serializedObject.FindProperty("HealthBarColor");
|
||||
HealthBarColorDamageProp = serializedObject.FindProperty("HealthBarDamageColor");
|
||||
HealthBarBackgroundColorProp = serializedObject.FindProperty("HealthBarBackgroundColor");
|
||||
NameTextColorProp = serializedObject.FindProperty("NameTextColor");
|
||||
LevelTextColorProp = serializedObject.FindProperty("LevelTextColor");
|
||||
AINameUIOutlineColorProp = serializedObject.FindProperty("AINameUIOutlineColor");
|
||||
AILevelUIOutlineColorProp = serializedObject.FindProperty("AILevelUIOutlineColor");
|
||||
AINameFontProp = serializedObject.FindProperty("AINameFont");
|
||||
AILevelFontProp = serializedObject.FindProperty("AILevelFont");
|
||||
|
||||
//String
|
||||
UITagProp = serializedObject.FindProperty("UITag");
|
||||
CameraTagProp = serializedObject.FindProperty("CameraTag");
|
||||
AINameProp = serializedObject.FindProperty("AIName");
|
||||
AITitleProp = serializedObject.FindProperty("AITitle");
|
||||
AILevelProp = serializedObject.FindProperty("AILevel");
|
||||
|
||||
//Objects
|
||||
HealthBarImageProp = serializedObject.FindProperty("HealthBarImage");
|
||||
HealthBarBackgroundImageProp = serializedObject.FindProperty("HealthBarBackgroundImage");
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
FoldoutStyle = CustomEditorProperties.UpdateEditorStyles();
|
||||
EmeraldUI self = (EmeraldUI)target;
|
||||
serializedObject.Update();
|
||||
|
||||
CustomEditorProperties.BeginScriptHeaderNew("UI", UIEditorIcon, new GUIContent(), HideSettingsFoldout);
|
||||
|
||||
if (!HideSettingsFoldout.boolValue)
|
||||
{
|
||||
EditorGUILayout.Space();
|
||||
UISettings(self);
|
||||
EditorGUILayout.Space();
|
||||
NameTextSettings(self);
|
||||
EditorGUILayout.Space();
|
||||
LevelTextSettings(self);
|
||||
EditorGUILayout.Space();
|
||||
HealthbarSettings(self);
|
||||
EditorGUILayout.Space();
|
||||
CombatTextSettings(self);
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
|
||||
CustomEditorProperties.EndScriptHeader();
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
|
||||
void UISettings (EmeraldUI self)
|
||||
{
|
||||
UISettingsFoldoutProp.boolValue = CustomEditorProperties.Foldout(UISettingsFoldoutProp.boolValue, "UI Setup", true, FoldoutStyle);
|
||||
|
||||
if (UISettingsFoldoutProp.boolValue)
|
||||
{
|
||||
CustomEditorProperties.BeginFoldoutWindowBox();
|
||||
|
||||
CustomEditorProperties.TextTitleWithDescription("UI Setup", "Controls the use and setup of Emerald's built-in UI. In order for the UI to be visible, a player of the appropriate tag must enter an AI's trigger radius. " +
|
||||
"You can set an AI's UI Tag under the Detection and Tag tab.", true);
|
||||
|
||||
GUI.backgroundColor = new Color(1f, 1, 0.25f, 0.25f);
|
||||
EditorGUILayout.LabelField("In order for the UI system to work correctly, you will need to assign a Tag and Layer. This is typically your Player's Tag and Layer. " +
|
||||
"This is used to make the UI system more efficient by only running when the appropriate objects are detected. You will also need to apply your player's camera Tag so the UI can be properly positioned.", EditorStyles.helpBox);
|
||||
GUI.backgroundColor = Color.white;
|
||||
|
||||
EditorGUILayout.Space();
|
||||
CustomEditorProperties.CustomTagField(new Rect(), new GUIContent(), CameraTagProp, "Camera Tag");
|
||||
CustomEditorProperties.CustomHelpLabelField("The Camera Tag is the Unity Tag that your player uses. The Camera is needed to properly position the UI.", true);
|
||||
|
||||
CustomEditorProperties.CustomTagField(new Rect(), new GUIContent(), UITagProp, "UI Tag");
|
||||
CustomEditorProperties.CustomHelpLabelField("The UI Tag is the Unity Tag that will trigger the AI's UI, when enabled.", true);
|
||||
|
||||
EditorGUILayout.PropertyField(UILayerMaskProp, new GUIContent("UI Layers"));
|
||||
CustomEditorProperties.CustomHelpLabelField("The UI Layers controls what layers this AI will detect to enable the their UI, if the object also has the appropriate UI Tag. This is typically used for players.", false);
|
||||
|
||||
if (UILayerMaskProp.intValue == 0 || UILayerMaskProp.intValue == 1)
|
||||
{
|
||||
GUI.backgroundColor = new Color(10f, 0.0f, 0.0f, 0.25f);
|
||||
EditorGUILayout.LabelField("The UI Layers cannot contain Nothing, Default, or Everything.", EditorStyles.helpBox);
|
||||
GUI.backgroundColor = Color.white;
|
||||
}
|
||||
|
||||
EditorGUILayout.Space();
|
||||
EditorGUILayout.PropertyField(MaxUIScaleSizeProp, new GUIContent("Max UI Scale"));
|
||||
CustomEditorProperties.CustomHelpLabelField("Controls the max size the UI will be scaled when the player is getting further away from an AI's UI.", true);
|
||||
CustomEditorProperties.EndFoldoutWindowBox();
|
||||
}
|
||||
}
|
||||
|
||||
void NameTextSettings (EmeraldUI self)
|
||||
{
|
||||
NameTextFoldoutProp.boolValue = CustomEditorProperties.Foldout(NameTextFoldoutProp.boolValue, "Name Text Settings", true, FoldoutStyle);
|
||||
|
||||
if (NameTextFoldoutProp.boolValue)
|
||||
{
|
||||
CustomEditorProperties.BeginFoldoutWindowBox();
|
||||
CustomEditorProperties.TextTitleWithDescription("Name Text Settings", "Settings for displaying and positioning this AI's Name using Emerald AI's built-in (Unity-based) UI System.", true);
|
||||
|
||||
EditorGUILayout.PropertyField(DisplayAINameProp, new GUIContent("Display AI Name"));
|
||||
CustomEditorProperties.CustomHelpLabelField("Enables or disables the display of the AI's name. When enabled, the AI's name will be visible above its health bar.", true);
|
||||
|
||||
if (self.DisplayAIName == YesOrNo.Yes)
|
||||
{
|
||||
CustomEditorProperties.BeginIndent();
|
||||
|
||||
EditorGUILayout.PropertyField(AINameProp, new GUIContent("AI's Name"));
|
||||
CustomEditorProperties.CustomHelpLabelField("The name of the AI. This can be displayed with Emerald's built-in UI system or a custom one.", true);
|
||||
EditorGUILayout.Space();
|
||||
|
||||
EditorGUILayout.PropertyField(UseCustomFontAINameProp, new GUIContent("Use Custom Name Font"));
|
||||
CustomEditorProperties.CustomHelpLabelField("Controls whether or not the Name Text font can be customized.", false);
|
||||
EditorGUILayout.Space();
|
||||
|
||||
if (self.UseCustomFontAIName == YesOrNo.Yes)
|
||||
{
|
||||
CustomEditorProperties.BeginIndent();
|
||||
EditorGUILayout.PropertyField(AINameFontProp, new GUIContent("Name Font"));
|
||||
CustomEditorProperties.CustomHelpLabelField("Controls the font of the AI's Name Text.", true);
|
||||
CustomEditorProperties.EndIndent();
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
|
||||
EditorGUILayout.PropertyField(AINamePosProp, new GUIContent("AI Name Position"));
|
||||
CustomEditorProperties.CustomHelpLabelField("Controls the position of the AI's name text.", true);
|
||||
EditorGUILayout.Space();
|
||||
|
||||
EditorGUILayout.PropertyField(NameTextFontSizeProp, new GUIContent("AI Name Font Size"));
|
||||
CustomEditorProperties.CustomHelpLabelField("Controls the size of the AI's name text.", true);
|
||||
EditorGUILayout.Space();
|
||||
|
||||
EditorGUILayout.PropertyField(NameTextColorProp, new GUIContent("AI Name Color"));
|
||||
CustomEditorProperties.CustomHelpLabelField("Controls the color of the AI's name text.", true);
|
||||
EditorGUILayout.Space();
|
||||
|
||||
EditorGUILayout.PropertyField(UseAINameUIOutlineEffectProp, new GUIContent("Use Outline on Name Text"));
|
||||
CustomEditorProperties.CustomHelpLabelField("Controls whether or not the AI's Name UI will use an Outline Effect.", true);
|
||||
EditorGUILayout.Space();
|
||||
|
||||
if (self.UseAINameUIOutlineEffect == YesOrNo.Yes)
|
||||
{
|
||||
CustomEditorProperties.BeginIndent();
|
||||
|
||||
EditorGUILayout.PropertyField(AINameUIOutlineColorProp, new GUIContent("Name Text Outline Color"));
|
||||
CustomEditorProperties.CustomHelpLabelField("Controls the color of the AI's Name Text Outline.", true);
|
||||
EditorGUILayout.Space();
|
||||
|
||||
EditorGUILayout.PropertyField(AINameUIOutlineSizeProp, new GUIContent("Name Text Outline Size"));
|
||||
CustomEditorProperties.CustomHelpLabelField("Controls the size of the AI's Name Text Outline.", true);
|
||||
EditorGUILayout.Space();
|
||||
|
||||
CustomEditorProperties.EndIndent();
|
||||
}
|
||||
|
||||
EditorGUILayout.PropertyField(DisplayAITitleProp, new GUIContent("Display AI Title"));
|
||||
CustomEditorProperties.CustomHelpLabelField("Enables or disables the display of the AI's title. When enabled, the AI's title will be visible above its health bar.", false);
|
||||
|
||||
if (self.DisplayAITitle == YesOrNo.Yes)
|
||||
{
|
||||
CustomEditorProperties.BeginIndent();
|
||||
|
||||
EditorGUILayout.PropertyField(AITitleProp, new GUIContent("AI's Title"));
|
||||
CustomEditorProperties.CustomHelpLabelField("The title of the AI. This can be displayed with Emerald's built-in UI system or a custom one.", true);
|
||||
EditorGUILayout.Space();
|
||||
|
||||
EditorGUILayout.PropertyField(AINameLineSpacingProp, new GUIContent("Name Line Spacing"));
|
||||
CustomEditorProperties.CustomHelpLabelField("Controls the line spacing between the AI's Name and the AI's Title.", true);
|
||||
|
||||
CustomEditorProperties.EndIndent();
|
||||
}
|
||||
|
||||
EditorGUILayout.Space();
|
||||
CustomEditorProperties.EndIndent();
|
||||
}
|
||||
|
||||
EditorGUILayout.Space();
|
||||
CustomEditorProperties.EndFoldoutWindowBox();
|
||||
}
|
||||
}
|
||||
|
||||
void LevelTextSettings(EmeraldUI self)
|
||||
{
|
||||
LevelTextFoldoutProp.boolValue = CustomEditorProperties.Foldout(LevelTextFoldoutProp.boolValue, "Level Text Settings", true, FoldoutStyle);
|
||||
|
||||
if (LevelTextFoldoutProp.boolValue)
|
||||
{
|
||||
CustomEditorProperties.BeginFoldoutWindowBox();
|
||||
CustomEditorProperties.TextTitleWithDescription("Name Text Settings", "Settings for displaying and positioning this AI's Level using Emerald AI's built-in (Unity-based) UI System.", true);
|
||||
|
||||
//TODO: Remove this limitation?
|
||||
/*
|
||||
if (self.AutoCreateHealthBars == YesOrNo.No)
|
||||
{
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
GUILayout.Space(10);
|
||||
EditorGUILayout.BeginVertical();
|
||||
GUI.backgroundColor = new Color(10f, 0.0f, 0.0f, 0.25f);
|
||||
EditorGUILayout.LabelField("You must have Auto Create Health Bars enabled to use this feature.", EditorStyles.helpBox);
|
||||
GUI.backgroundColor = Color.white;
|
||||
EditorGUILayout.EndVertical();
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
*/
|
||||
EditorGUILayout.PropertyField(DisplayAILevelProp, new GUIContent("Display AI Level"));
|
||||
CustomEditorProperties.CustomHelpLabelField("Enables or disables the display of the AI's level. When enabled, the AI's level will be visible to the left of its health bar.", true);
|
||||
|
||||
if (self.DisplayAILevel == YesOrNo.Yes)
|
||||
{
|
||||
CustomEditorProperties.BeginIndent();
|
||||
|
||||
CustomEditorProperties.CustomIntField(new Rect(), new GUIContent(), AILevelProp, "AI's Level");
|
||||
CustomEditorProperties.CustomHelpLabelField("The level of the AI. This can be displayed with Emerald's built-in UI system or a custom one.", true);
|
||||
EditorGUILayout.Space();
|
||||
|
||||
EditorGUILayout.PropertyField(UseCustomFontAILevelProp, new GUIContent("Use Custom Level Font"));
|
||||
CustomEditorProperties.CustomHelpLabelField("Controls whether or not the Level Text font can be customized.", true);
|
||||
EditorGUILayout.Space();
|
||||
|
||||
if (self.UseCustomFontAILevel == YesOrNo.Yes)
|
||||
{
|
||||
EditorGUILayout.PropertyField(AILevelFontProp, new GUIContent("Level Font"));
|
||||
CustomEditorProperties.CustomHelpLabelField("Controls the font of the AI's Level Text.", true);
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
|
||||
EditorGUILayout.PropertyField(AILevelPosProp, new GUIContent("AI Level Position"));
|
||||
CustomEditorProperties.CustomHelpLabelField("Controls the position of the AI's level text.", true);
|
||||
EditorGUILayout.Space();
|
||||
|
||||
EditorGUILayout.PropertyField(LevelTextColorProp, new GUIContent("Level Color"));
|
||||
CustomEditorProperties.CustomHelpLabelField("Controls the color of the AI's Level Text.", true);
|
||||
EditorGUILayout.Space();
|
||||
|
||||
EditorGUILayout.PropertyField(UseAILevelUIOutlineEffectProp, new GUIContent("Use Outline on Level Text"));
|
||||
CustomEditorProperties.CustomHelpLabelField("Controls whether or not the AI's Level UI will use an Outline Effect.", true);
|
||||
EditorGUILayout.Space();
|
||||
|
||||
if (self.UseAILevelUIOutlineEffect == YesOrNo.Yes)
|
||||
{
|
||||
CustomEditorProperties.BeginIndent();
|
||||
|
||||
EditorGUILayout.PropertyField(AILevelUIOutlineColorProp, new GUIContent("Level Text Outline Color"));
|
||||
CustomEditorProperties.CustomHelpLabelField("Controls the color of the AI's Level Text Outline.", true);
|
||||
EditorGUILayout.Space();
|
||||
|
||||
EditorGUILayout.PropertyField(AILevelUIOutlineSizeProp, new GUIContent("Level Text Outline Size"));
|
||||
CustomEditorProperties.CustomHelpLabelField("Controls the size of the AI's Level Text Outline.", true);
|
||||
EditorGUILayout.Space();
|
||||
|
||||
CustomEditorProperties.EndIndent();
|
||||
}
|
||||
|
||||
CustomEditorProperties.EndIndent();
|
||||
}
|
||||
|
||||
CustomEditorProperties.EndFoldoutWindowBox();
|
||||
}
|
||||
}
|
||||
|
||||
void HealthbarSettings (EmeraldUI self)
|
||||
{
|
||||
HealthBarsFoldoutProp.boolValue = CustomEditorProperties.Foldout(HealthBarsFoldoutProp.boolValue, "Health Bar Settings", true, FoldoutStyle);
|
||||
|
||||
if (HealthBarsFoldoutProp.boolValue)
|
||||
{
|
||||
CustomEditorProperties.BeginFoldoutWindowBox();
|
||||
CustomEditorProperties.TextTitleWithDescription("Health Bar Settings", "Settings for displaying and positioning this AI's Health Bar using Emerald AI's built-in (Unity-based) UI System.", true);
|
||||
|
||||
EditorGUILayout.PropertyField(CreateHealthBarsProp, new GUIContent("Auto Create Health Bars"));
|
||||
CustomEditorProperties.CustomHelpLabelField("Enables or disables the use of Emerald automatically creating health bars for your AI. Enabling this will open up additional settings.", true);
|
||||
EditorGUILayout.Space();
|
||||
|
||||
if (self.AutoCreateHealthBars == YesOrNo.Yes)
|
||||
{
|
||||
CustomEditorProperties.BeginIndent();
|
||||
|
||||
EditorGUILayout.PropertyField(HealthBarPosProp, new GUIContent("Health Bar Position"));
|
||||
CustomEditorProperties.CustomHelpLabelField("Controls the starting position of the AI's created health bar.", true);
|
||||
EditorGUILayout.Space();
|
||||
|
||||
EditorGUILayout.PropertyField(HealthBarScaleProp, new GUIContent("Health Bar Scale"));
|
||||
CustomEditorProperties.CustomHelpLabelField("Controls the scale of the AI's created health bar.", true);
|
||||
EditorGUILayout.Space();
|
||||
|
||||
EditorGUILayout.PropertyField(HealthBarColorProp, new GUIContent("Health Bar Color"));
|
||||
CustomEditorProperties.CustomHelpLabelField("Controls the color of the AI's health bar.", true);
|
||||
EditorGUILayout.Space();
|
||||
|
||||
EditorGUILayout.PropertyField(HealthBarColorDamageProp, new GUIContent("Health Bar Damage Color"));
|
||||
CustomEditorProperties.CustomHelpLabelField("Controls the color of the AI's health bar when damaged.", true);
|
||||
EditorGUILayout.Space();
|
||||
|
||||
EditorGUILayout.PropertyField(HealthBarBackgroundColorProp, new GUIContent("Background Color"));
|
||||
CustomEditorProperties.CustomHelpLabelField("Controls the background color of the AI's health bar.", true);
|
||||
EditorGUILayout.Space();
|
||||
|
||||
EditorGUILayout.PropertyField(CustomizeHealthBarProp, new GUIContent("Use Custom Health Bar"));
|
||||
CustomEditorProperties.CustomHelpLabelField("Allows you to use custom sprites for the AI's health bar.", true);
|
||||
EditorGUILayout.Space();
|
||||
|
||||
if (self.UseCustomHealthBar == YesOrNo.Yes)
|
||||
{
|
||||
EditorGUILayout.LabelField("Health Bar Sprites", EditorStyles.boldLabel);
|
||||
EditorGUILayout.Space();
|
||||
|
||||
CustomEditorProperties.CustomObjectField(new Rect(), new GUIContent(), HealthBarImageProp, "Bar", typeof(Sprite), true);
|
||||
CustomEditorProperties.CustomHelpLabelField("Customizes the health bar sprite for the AI's health bar.", true);
|
||||
|
||||
CustomEditorProperties.CustomObjectField(new Rect(), new GUIContent(), HealthBarBackgroundImageProp, "Bar Background", typeof(Sprite), true);
|
||||
CustomEditorProperties.CustomHelpLabelField("Customizes the health bar's background sprite for the AI's health bar.", true);
|
||||
}
|
||||
|
||||
CustomEditorProperties.EndIndent();
|
||||
}
|
||||
|
||||
CustomEditorProperties.EndFoldoutWindowBox();
|
||||
}
|
||||
}
|
||||
|
||||
void CombatTextSettings (EmeraldUI self)
|
||||
{
|
||||
CombatTextFoldoutProp.boolValue = CustomEditorProperties.Foldout(CombatTextFoldoutProp.boolValue, "Combat Text Settings", true, FoldoutStyle);
|
||||
|
||||
if (CombatTextFoldoutProp.boolValue)
|
||||
{
|
||||
CustomEditorProperties.BeginFoldoutWindowBox();
|
||||
CustomEditorProperties.TextTitleWithDescription("Combat Text Settings", "A shortcut to Emerald AI's built-in (global) Combat Text System.", true);
|
||||
|
||||
CustomEditorProperties.CustomHelpLabelField("The Combat Text System can be adjusted through the Combat Text Manager. These settings are applied globally.", false);
|
||||
var ButtonStyle = new GUIStyle(GUI.skin.button);
|
||||
if (GUILayout.Button("Open Combat Text Manager", ButtonStyle))
|
||||
{
|
||||
EditorWindow CTM = EditorWindow.GetWindow(typeof(EmeraldCombatTextManager), true, "Combat Text Manager");
|
||||
CTM.minSize = new Vector2(600f, 725f);
|
||||
}
|
||||
|
||||
EditorGUILayout.Space();
|
||||
EditorGUILayout.Space();
|
||||
CustomEditorProperties.EndFoldoutWindowBox();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnSceneGUI()
|
||||
{
|
||||
EmeraldUI self = (EmeraldUI)target;
|
||||
DrawUIPositions(self);
|
||||
}
|
||||
|
||||
void DrawUIPositions(EmeraldUI self)
|
||||
{
|
||||
if (self == null) return;
|
||||
|
||||
if (self.DisplayAIName == YesOrNo.Yes && self.NameTextFoldout)
|
||||
{
|
||||
Handles.color = self.NameTextColor;
|
||||
Handles.DrawLine(new Vector3(self.transform.localPosition.x, self.transform.localPosition.y, self.transform.localPosition.z),
|
||||
new Vector3(self.AINamePos.x, self.AINamePos.y, self.AINamePos.z) + self.transform.localPosition);
|
||||
Handles.color = Color.white;
|
||||
}
|
||||
|
||||
if (self.AutoCreateHealthBars == YesOrNo.Yes && self.HealthBarsFoldout)
|
||||
{
|
||||
Handles.color = self.HealthBarColor;
|
||||
Handles.DrawLine(new Vector3(self.transform.localPosition.x + 0.25f, self.transform.localPosition.y, self.transform.localPosition.z),
|
||||
new Vector3(self.HealthBarPos.x + 0.25f, self.HealthBarPos.y, self.HealthBarPos.z) + self.transform.localPosition);
|
||||
Handles.color = Color.white;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ce109207489d6094cb34ad269047b4d0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,65 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using UnityEditorInternal;
|
||||
|
||||
namespace EmeraldAI.Utility
|
||||
{
|
||||
[CustomEditor(typeof(EmeraldWeaponCollision))]
|
||||
[CanEditMultipleObjects]
|
||||
public class EmeraldWeaponCollisionEditor : Editor
|
||||
{
|
||||
GUIStyle FoldoutStyle;
|
||||
Texture WeaponCollisionEditorIcon;
|
||||
SerializedProperty CollisionBoxColor, HideSettingsFoldout, WeaponCollisionFoldout;
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
if (WeaponCollisionEditorIcon == null) WeaponCollisionEditorIcon = Resources.Load("Editor Icons/EmeraldWeaponCollision") as Texture;
|
||||
EmeraldWeaponCollision self = (EmeraldWeaponCollision)target;
|
||||
self.WeaponCollider = self.GetComponent<BoxCollider>();
|
||||
CollisionBoxColor = serializedObject.FindProperty("CollisionBoxColor");
|
||||
HideSettingsFoldout = serializedObject.FindProperty("HideSettingsFoldout");
|
||||
WeaponCollisionFoldout = serializedObject.FindProperty("WeaponCollisionFoldout");
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
FoldoutStyle = CustomEditorProperties.UpdateEditorStyles();
|
||||
serializedObject.Update();
|
||||
|
||||
CustomEditorProperties.BeginScriptHeaderNew("Weapon Collision", WeaponCollisionEditorIcon, new GUIContent(), HideSettingsFoldout);
|
||||
|
||||
if (!HideSettingsFoldout.boolValue)
|
||||
{
|
||||
EditorGUILayout.Space();
|
||||
WeaponCollisionSettings();
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
|
||||
CustomEditorProperties.EndScriptHeader();
|
||||
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
|
||||
void WeaponCollisionSettings ()
|
||||
{
|
||||
WeaponCollisionFoldout.boolValue = EditorGUILayout.Foldout(WeaponCollisionFoldout.boolValue, "Weapon Collision Settings", true, FoldoutStyle);
|
||||
|
||||
if (WeaponCollisionFoldout.boolValue)
|
||||
{
|
||||
CustomEditorProperties.BeginFoldoutWindowBox();
|
||||
CustomEditorProperties.TextTitleWithDescription("Weapon Collision Settings", "Adjust the size of the Box Collider (using the Box Collider component) to position the collider to an AI's weapon. The Weapon Collision is intended for melee related attacks. In order for " +
|
||||
"the Weapon Collision component to work, it needs to be enabled through an Animation Event.", true);
|
||||
|
||||
EditorGUILayout.PropertyField(CollisionBoxColor, new GUIContent("Collision Box Color"));
|
||||
CustomEditorProperties.CustomHelpLabelField("Controls the color of the Collision Box.", true);
|
||||
|
||||
EditorGUILayout.Space();
|
||||
CustomEditorProperties.EndFoldoutWindowBox();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 62077336c47d2a744a0d815447c7b80d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,214 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using UnityEditorInternal;
|
||||
using System.Linq;
|
||||
|
||||
namespace EmeraldAI.Utility
|
||||
{
|
||||
[System.Serializable]
|
||||
[CustomEditor(typeof(LocationBasedDamage))]
|
||||
[CanEditMultipleObjects]
|
||||
public class LocationBasedDamageEditor : Editor
|
||||
{
|
||||
GUIStyle FoldoutStyle;
|
||||
Texture LBDEditorIcon;
|
||||
ReorderableList ColliderList;
|
||||
string ColliderListState;
|
||||
SerializedProperty HideSettingsFoldout, LBDSettingsFoldout, LBDComponentsTag, SetCollidersLayerAndTag;
|
||||
List<string> layers = new List<string>();
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
if (LBDEditorIcon == null) LBDEditorIcon = Resources.Load("Editor Icons/EmeraldLBD") as Texture;
|
||||
HideSettingsFoldout = serializedObject.FindProperty("HideSettingsFoldout");
|
||||
LBDSettingsFoldout = serializedObject.FindProperty("LBDSettingsFoldout");
|
||||
LBDComponentsTag = serializedObject.FindProperty("LBDComponentsTag");
|
||||
SetCollidersLayerAndTag = serializedObject.FindProperty("SetCollidersLayerAndTag");
|
||||
InitializeList();
|
||||
InitializeLayers();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get all the layers in the project so the user can choose one to apply to their LBD components.
|
||||
/// This layer will also be added to a static layermask and automatically added to every AI's obstruction detection layermask.
|
||||
/// This is needed to stop the LBD components from causing obstructions. Doing it globally allows all AI to receive the change automatically
|
||||
/// so users don't have to manually track or set layers for every AI in their project.
|
||||
/// </summary>
|
||||
void InitializeLayers()
|
||||
{
|
||||
for (int i = 0; i < 32; i++)
|
||||
{
|
||||
if (LayerMask.LayerToName(i) != "")
|
||||
layers.Add(LayerMask.LayerToName(i));
|
||||
else
|
||||
layers.Add("Empty");
|
||||
}
|
||||
}
|
||||
|
||||
void InitializeList ()
|
||||
{
|
||||
//Label Style
|
||||
var LabelStyle = new GUIStyle();
|
||||
LabelStyle.fontStyle = FontStyle.Bold;
|
||||
LabelStyle.active.textColor = Color.white;
|
||||
LabelStyle.normal.textColor = Color.white;
|
||||
|
||||
ColliderList = new ReorderableList(serializedObject, serializedObject.FindProperty("ColliderList"), false, true, false, true);
|
||||
ColliderList.drawHeaderCallback = rect =>
|
||||
{
|
||||
EditorGUI.LabelField(rect, "Collider List", EditorStyles.boldLabel);
|
||||
};
|
||||
ColliderList.drawElementCallback =
|
||||
(Rect rect, int index, bool isActive, bool isFocused) =>
|
||||
{
|
||||
var element = ColliderList.serializedProperty.GetArrayElementAtIndex(index);
|
||||
ColliderList.elementHeight = EditorGUIUtility.singleLineHeight * 2.5f;
|
||||
|
||||
//Label
|
||||
if (element.FindPropertyRelative("ColliderObject").objectReferenceValue != null)
|
||||
{
|
||||
EditorGUI.PrefixLabel(new Rect(rect.x + 120, rect.y, rect.width - 70, EditorGUIUtility.singleLineHeight),
|
||||
new GUIContent(element.FindPropertyRelative("ColliderObject").objectReferenceValue.name), LabelStyle);
|
||||
|
||||
//Select Button
|
||||
if (GUI.Button(new Rect(rect.x, rect.y, 110, EditorGUIUtility.singleLineHeight), "Select Collider"))
|
||||
{
|
||||
Selection.activeObject = element.FindPropertyRelative("ColliderObject").objectReferenceValue;
|
||||
}
|
||||
|
||||
//Multiplier
|
||||
element.FindPropertyRelative("DamageMultiplier").floatValue = EditorGUI.Slider(new Rect(rect.x, rect.y + EditorGUIUtility.singleLineHeight, rect.width, EditorGUIUtility.singleLineHeight), element.FindPropertyRelative("ColliderObject").objectReferenceValue.name + " Multiplier", element.FindPropertyRelative("DamageMultiplier").floatValue, 0, 25);
|
||||
}
|
||||
else
|
||||
{
|
||||
GUI.color = Color.red;
|
||||
EditorGUI.PrefixLabel(new Rect(rect.x + 120, rect.y, rect.width - 120, EditorGUIUtility.singleLineHeight), new GUIContent("Null - Please Remove"), LabelStyle);
|
||||
GUILayout.FlexibleSpace();
|
||||
GUI.color = Color.white;
|
||||
|
||||
GUI.contentColor = Color.red;
|
||||
//Select Button
|
||||
if (GUI.Button(new Rect(rect.x, rect.y, 110, EditorGUIUtility.singleLineHeight), "Remove"))
|
||||
{
|
||||
LocationBasedDamage self = (LocationBasedDamage)target;
|
||||
self.ColliderList.RemoveAt(index);
|
||||
}
|
||||
GUI.contentColor = Color.white;
|
||||
|
||||
EditorGUI.BeginDisabledGroup(true);
|
||||
element.FindPropertyRelative("DamageMultiplier").floatValue = EditorGUI.Slider(new Rect(rect.x, rect.y + EditorGUIUtility.singleLineHeight, rect.width, EditorGUIUtility.singleLineHeight), "Null" + " Multiplier", element.FindPropertyRelative("DamageMultiplier").floatValue, 0, 25);
|
||||
EditorGUI.EndDisabledGroup();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
FoldoutStyle = CustomEditorProperties.UpdateEditorStyles();
|
||||
LocationBasedDamage self = (LocationBasedDamage)target;
|
||||
serializedObject.Update();
|
||||
|
||||
CustomEditorProperties.BeginScriptHeaderNew("Location Based Damage", LBDEditorIcon, new GUIContent(), HideSettingsFoldout);
|
||||
|
||||
if (!HideSettingsFoldout.boolValue)
|
||||
{
|
||||
EditorGUILayout.Space();
|
||||
LBDSettings(self);
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
|
||||
CustomEditorProperties.EndScriptHeader();
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
|
||||
void LBDSettings (LocationBasedDamage self)
|
||||
{
|
||||
LBDSettingsFoldout.boolValue = EditorGUILayout.Foldout(LBDSettingsFoldout.boolValue, "Location Based Damage Settings", true, FoldoutStyle);
|
||||
|
||||
if (LBDSettingsFoldout.boolValue)
|
||||
{
|
||||
CustomEditorProperties.BeginFoldoutWindowBox();
|
||||
CustomEditorProperties.TextTitleWithDescription("Location Based Damage Settings", "The Location Based Damage component allows each collider to detect damage and apply a customizable damage multiplier based on the damage receieved. The hit effect that will play upon impact, " +
|
||||
"and at the position the hit is detected, is based off of the AI's Hit Effects List (Located under AI's Settings>Combat>Hit Effect)", false);
|
||||
|
||||
CustomEditorProperties.TutorialButton("For a tutorial on using the Location Based Damage component, please see the tutorial below. Note: The LBD uses different code to damage an AI.",
|
||||
"https://black-horizon-studios.gitbook.io/emerald-ai-wiki/emerald-components-optional/location-based-damage-component");
|
||||
EditorGUILayout.Space();
|
||||
|
||||
CustomEditorProperties.CustomPropertyField(SetCollidersLayerAndTag, "Set Colliders Layer and Tag", "Controls whether or not the Location Based Dmaage component will set the detected collider's tag and layer. Users can customize the tag and layer by enabling this setting.", true);
|
||||
|
||||
if (SetCollidersLayerAndTag.boolValue)
|
||||
{
|
||||
CustomEditorProperties.BeginIndent();
|
||||
CustomEditorProperties.FactionListEnum(new Rect(), GUIContent.none, serializedObject.FindProperty("LBDComponentsLayer"), "Collider Layer", layers);
|
||||
CustomEditorProperties.CustomHelpLabelField("Sets the layer of the Location Based Damage colliders. This is layer will automatically be added to every AI's Obstruction Detection Layermask so the components will not obstruct their line of sight." +
|
||||
" It is very important that this layer is not your targets' layers and that it is not Default.", true);
|
||||
EditorGUILayout.Space();
|
||||
|
||||
CustomEditorProperties.CustomTagField(new Rect(), new GUIContent(), LBDComponentsTag, "Collider Tag");
|
||||
CustomEditorProperties.CustomHelpLabelField("Sets the tag of the Location Based Damage colliders. It is recommended that the tag is set to something other than Untagged.", true);
|
||||
EditorGUILayout.Space();
|
||||
|
||||
CustomEditorProperties.FactionListEnum(new Rect(), GUIContent.none, serializedObject.FindProperty("DeadLBDComponentsLayer"), "Dead Collider Layer", layers);
|
||||
CustomEditorProperties.CustomHelpLabelField("Sets the layer of the Location Based Damage colliders when an AI dies.", true);
|
||||
EditorGUILayout.Space();
|
||||
CustomEditorProperties.EndIndent();
|
||||
}
|
||||
else
|
||||
{
|
||||
GUILayout.Space(-15);
|
||||
CustomEditorProperties.DisplayWarningMessage("It is recommended that this setting is kept on, unless you are handling the colliders' layer and tag manually. The layer should not be set to Default. Not properly managing this can result in detection issues");
|
||||
}
|
||||
|
||||
EditorGUILayout.Space();
|
||||
EditorGUILayout.Space();
|
||||
|
||||
EditorGUILayout.LabelField("Gets all colliders within the AI and applies Location Based Damage Area components to them.", EditorStyles.helpBox);
|
||||
if (GUILayout.Button("Get Colliders"))
|
||||
{
|
||||
var m_Colliders = self.GetComponentsInChildren<Collider>();
|
||||
|
||||
foreach (Collider C in m_Colliders)
|
||||
{
|
||||
if (C != null && C.gameObject != self.gameObject)
|
||||
{
|
||||
if (!self.ColliderList.Exists(x => x.ColliderObject == C))
|
||||
{
|
||||
LocationBasedDamage.LocationBasedDamageClass lbdc = new LocationBasedDamage.LocationBasedDamageClass(C, 1);
|
||||
self.ColliderList.Add(lbdc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
serializedObject.Update();
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
|
||||
if (self.ColliderList.Count == 0)
|
||||
{
|
||||
Debug.Log("There are no colliders within this AI. Please ensure that you have setup the AI with Unity's Ragdoll Wizard or a 3rd party ragdoll tool.");
|
||||
}
|
||||
}
|
||||
|
||||
if (GUILayout.Button("Clear Colliders") && EditorUtility.DisplayDialog("Clear Collider List?", "Are you sure you want to clear the AI's Collider List? This process cannot be undone.", "Clear", "Do Not Clear"))
|
||||
{
|
||||
self.ColliderList.Clear();
|
||||
serializedObject.Update();
|
||||
}
|
||||
|
||||
EditorGUILayout.HelpBox("You can remove an undesired collider by selecting the collider within the Collider List and pressing the - button on the bottom of the Collider List area.", MessageType.Info);
|
||||
|
||||
EditorGUILayout.Space();
|
||||
EditorGUILayout.Space();
|
||||
|
||||
ColliderList.DoLayoutList();
|
||||
|
||||
EditorGUILayout.Space();
|
||||
EditorGUILayout.Space();
|
||||
CustomEditorProperties.EndFoldoutWindowBox();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9826dfeb5581fd247993159fbf2d604d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,94 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
namespace EmeraldAI.Utility
|
||||
{
|
||||
[CustomEditor(typeof(TargetPositionModifier))]
|
||||
[CanEditMultipleObjects]
|
||||
[System.Serializable]
|
||||
public class TargetPositionModifierEditor : Editor
|
||||
{
|
||||
GUIStyle FoldoutStyle;
|
||||
Texture TPMEditorIcon;
|
||||
SerializedProperty PositionModifierProp, TransformSourceProp, GizmoRadiusProp, GizmoColorProp, TPMSettingsFoldout, HideSettingsFoldout;
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
InitializeProperties();
|
||||
}
|
||||
|
||||
void InitializeProperties()
|
||||
{
|
||||
if (TPMEditorIcon == null) TPMEditorIcon = Resources.Load("Editor Icons/EmeraldTPM") as Texture;
|
||||
PositionModifierProp = serializedObject.FindProperty("PositionModifier");
|
||||
TransformSourceProp = serializedObject.FindProperty("TransformSource");
|
||||
GizmoRadiusProp = serializedObject.FindProperty("GizmoRadius");
|
||||
GizmoColorProp = serializedObject.FindProperty("GizmoColor");
|
||||
TPMSettingsFoldout = serializedObject.FindProperty("TPMSettingsFoldout");
|
||||
HideSettingsFoldout = serializedObject.FindProperty("HideSettingsFoldout");
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
FoldoutStyle = CustomEditorProperties.UpdateEditorStyles();
|
||||
serializedObject.Update();
|
||||
|
||||
if (TransformSourceProp.objectReferenceValue == null)
|
||||
{
|
||||
CustomEditorProperties.DisplaySetupWarning("A Transform Source is required when using the Transform Position Source. Please assign one in order to use the Target Position Modifier.");
|
||||
}
|
||||
|
||||
CustomEditorProperties.BeginScriptHeaderNew("Target Position Modifier", TPMEditorIcon, new GUIContent(), HideSettingsFoldout);
|
||||
|
||||
if (!HideSettingsFoldout.boolValue)
|
||||
{
|
||||
EditorGUILayout.Space();
|
||||
TPMSettings();
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
|
||||
CustomEditorProperties.EndScriptHeader();
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
|
||||
void TPMSettings ()
|
||||
{
|
||||
TPMSettingsFoldout.boolValue = EditorGUILayout.Foldout(TPMSettingsFoldout.boolValue, "Target Position Modifier Settings", true, FoldoutStyle);
|
||||
|
||||
if (TPMSettingsFoldout.boolValue)
|
||||
{
|
||||
CustomEditorProperties.BeginFoldoutWindowBox();
|
||||
CustomEditorProperties.TextTitleWithDescription("Target Position Modifier Settings", "This system modifies the target height of targets allowing AI agents to target the sphere gizmo shown.", false);
|
||||
|
||||
CustomEditorProperties.NoticeTextDescription("Enusre that the gizmo does not go into the ground or this could make a target undetectable to AI. If you can't see the gizmo, ensure that Unity' Gizmos are enabled.", false);
|
||||
|
||||
CustomEditorProperties.TutorialButton("For a detailed tutorial on using the Target Position Modifier, please see the tutorial below.", "https://black-horizon-studios.gitbook.io/emerald-ai-wiki/emerald-components-optional/target-position-modifier-component");
|
||||
EditorGUILayout.Space();
|
||||
|
||||
if (TransformSourceProp.objectReferenceValue == null)
|
||||
{
|
||||
GUI.backgroundColor = new Color(10f, 0.0f, 0.0f, 0.25f);
|
||||
EditorGUILayout.LabelField("This field cannot be left blank", EditorStyles.helpBox);
|
||||
GUI.backgroundColor = Color.white;
|
||||
}
|
||||
EditorGUILayout.PropertyField(TransformSourceProp, new GUIContent("Transform Source"));
|
||||
CustomEditorProperties.CustomHelpLabelField("The Transform Source should be the transform you want the Target Position Modifier based off of. It is recommended that this is a bone transform that is close the the center of your AI such as its chest or spine.", true);
|
||||
|
||||
CustomEditorProperties.CustomFloatSlider(new Rect(), new GUIContent(), PositionModifierProp, "Height Modifier", -5, 5);
|
||||
CustomEditorProperties.CustomHelpLabelField("Controls the height offset of the position modifier.", true);
|
||||
|
||||
CustomEditorProperties.CustomFloatSlider(new Rect(), new GUIContent(), GizmoRadiusProp, "Gizmo Radius", 0.05f, 2.5f);
|
||||
CustomEditorProperties.CustomHelpLabelField("Controls the radius of the sphere gizmo.", true);
|
||||
|
||||
CustomEditorProperties.CustomColorField(new Rect(), new GUIContent(), GizmoColorProp, "Gizmo Color");
|
||||
CustomEditorProperties.CustomHelpLabelField("Controls the color of the sphere gizmo.", true);
|
||||
|
||||
EditorGUILayout.Space();
|
||||
EditorGUILayout.Space();
|
||||
CustomEditorProperties.EndFoldoutWindowBox();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 13b7c111a75a9254596e0a4cc07d4b3a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user