summaryrefslogtreecommitdiff
path: root/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Editor/Inspectors/FollowerEntityEditor.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Editor/Inspectors/FollowerEntityEditor.cs')
-rw-r--r--Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Editor/Inspectors/FollowerEntityEditor.cs224
1 files changed, 224 insertions, 0 deletions
diff --git a/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Editor/Inspectors/FollowerEntityEditor.cs b/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Editor/Inspectors/FollowerEntityEditor.cs
new file mode 100644
index 0000000..7742f29
--- /dev/null
+++ b/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Editor/Inspectors/FollowerEntityEditor.cs
@@ -0,0 +1,224 @@
+#if MODULE_ENTITIES
+using UnityEditor;
+using UnityEngine;
+using Pathfinding.RVO;
+using Pathfinding.ECS;
+using System.Linq;
+
+namespace Pathfinding {
+ [CustomEditor(typeof(FollowerEntity), true)]
+ [CanEditMultipleObjects]
+ public class FollowerEntityEditor : EditorBase {
+ bool debug = false;
+ bool tagPenaltiesOpen;
+
+ protected override void OnDisable () {
+ base.OnDisable();
+ EditorPrefs.SetBool("FollowerEntity.debug", debug);
+ EditorPrefs.SetBool("FollowerEntity.tagPenaltiesOpen", tagPenaltiesOpen);
+ }
+
+ protected override void OnEnable () {
+ base.OnEnable();
+ debug = EditorPrefs.GetBool("FollowerEntity.debug", false);
+ tagPenaltiesOpen = EditorPrefs.GetBool("FollowerEntity.tagPenaltiesOpen", false);
+ }
+
+ public override bool RequiresConstantRepaint () {
+ // When the debug inspector is open we want to update it every frame
+ // as the agent can move
+ return debug && Application.isPlaying;
+ }
+
+ protected void AutoRepathInspector () {
+ var mode = FindProperty("autoRepathBacking.mode");
+
+ PropertyField(mode, "Recalculate paths automatically");
+ if (!mode.hasMultipleDifferentValues) {
+ var modeValue = (AutoRepathPolicy.Mode)mode.enumValueIndex;
+ EditorGUI.indentLevel++;
+ var period = FindProperty("autoRepathBacking.period");
+ if (modeValue == AutoRepathPolicy.Mode.EveryNSeconds || modeValue == AutoRepathPolicy.Mode.Dynamic) {
+ FloatField(period, min: 0f);
+ }
+ if (modeValue == AutoRepathPolicy.Mode.Dynamic) {
+ EditorGUILayout.HelpBox("The path will be recalculated at least every " + period.floatValue.ToString("0.0") + " seconds, but more often if the destination changes quickly", MessageType.None);
+ }
+ EditorGUI.indentLevel--;
+ }
+ }
+
+ protected void DebugInspector () {
+ debug = EditorGUILayout.Foldout(debug, "Debug info");
+ if (debug) {
+ EditorGUI.indentLevel++;
+ EditorGUI.BeginDisabledGroup(true);
+ if (targets.Length == 1) {
+ var ai = target as FollowerEntity;
+ EditorGUILayout.Toggle("Reached Destination", ai.reachedDestination);
+ EditorGUILayout.Toggle("Reached End Of Path", ai.reachedEndOfPath);
+ EditorGUILayout.Toggle("Has Path", ai.hasPath);
+ EditorGUILayout.Toggle("Path Pending", ai.pathPending);
+ if (ai.isTraversingOffMeshLink) {
+ EditorGUILayout.Toggle("Traversing off-mesh link", true);
+ }
+ EditorGUI.EndDisabledGroup();
+
+ var newDestination = EditorGUILayout.Vector3Field("Destination", ai.destination);
+ if (ai.entityExists) ai.destination = newDestination;
+
+ EditorGUI.BeginDisabledGroup(true);
+ EditorGUILayout.LabelField("Remaining distance", ai.remainingDistance.ToString("0.00"));
+ EditorGUILayout.LabelField("Speed", ai.velocity.magnitude.ToString("0.00"));
+ } else {
+ int nReachedDestination = 0;
+ int nReachedEndOfPath = 0;
+ int nPending = 0;
+ for (int i = 0; i < targets.Length; i++) {
+ var ai = targets[i] as IAstarAI;
+ if (ai.reachedDestination) nReachedDestination++;
+ if (ai.reachedEndOfPath) nReachedEndOfPath++;
+ if (ai.pathPending) nPending++;
+ }
+ EditorGUILayout.LabelField("Reached Destination", nReachedDestination + " of " + targets.Length);
+ EditorGUILayout.LabelField("Reached End Of Path", nReachedEndOfPath + " of " + targets.Length);
+ EditorGUILayout.LabelField("Path Pending", nPending + " of " + targets.Length);
+ }
+ EditorGUI.EndDisabledGroup();
+ EditorGUI.indentLevel--;
+ }
+ }
+
+ void PathfindingSettingsInspector () {
+ bool anyCustomTraversalProvider = this.targets.Any(s => (s as FollowerEntity).pathfindingSettings.traversalProvider != null);
+ if (anyCustomTraversalProvider) {
+ EditorGUILayout.HelpBox("Custom traversal provider active", MessageType.None);
+ }
+
+ PropertyField("managedState.pathfindingSettings.graphMask", "Traversable Graphs");
+
+ tagPenaltiesOpen = EditorGUILayout.Foldout(tagPenaltiesOpen, new GUIContent("Tags", "Settings for each tag"));
+ if (tagPenaltiesOpen) {
+ EditorGUI.indentLevel++;
+ var traversableTags = this.targets.Select(s => (s as FollowerEntity).pathfindingSettings.traversableTags).ToArray();
+ SeekerEditor.TagsEditor(FindProperty("managedState.pathfindingSettings.tagPenalties"), traversableTags);
+ for (int i = 0; i < targets.Length; i++) {
+ (targets[i] as FollowerEntity).pathfindingSettings.traversableTags = traversableTags[i];
+ }
+ EditorGUI.indentLevel--;
+ }
+ }
+
+ protected override void Inspector () {
+ Undo.RecordObjects(targets, "Modify FollowerEntity settings");
+ EditorGUI.BeginChangeCheck();
+ Section("Shape");
+ FloatField("shape.radius", min: 0.01f);
+ FloatField("shape.height", min: 0.01f);
+ Popup("orientationBacking", new [] { new GUIContent("ZAxisForward (for 3D games)"), new GUIContent("YAxisForward (for 2D games)") }, "Orientation");
+
+ Section("Movement");
+ FloatField("movement.follower.speed", min: 0f);
+ FloatField("movement.follower.rotationSpeed", min: 0f);
+ var maxRotationSpeed = FindProperty("movement.follower.rotationSpeed");
+ FloatField("movement.follower.maxRotationSpeed", min: maxRotationSpeed.hasMultipleDifferentValues ? 0f : maxRotationSpeed.floatValue);
+ if (ByteAsToggle("movement.follower.allowRotatingOnSpotBacking", "Allow Rotating On The Spot")) {
+ EditorGUI.indentLevel++;
+ FloatField("movement.follower.maxOnSpotRotationSpeed", min: 0f);
+ FloatField("movement.follower.slowdownTimeWhenTurningOnSpot", min: 0f);
+ EditorGUI.indentLevel--;
+ }
+ Slider("movement.positionSmoothing", left: 0f, right: 0.5f);
+ Slider("movement.rotationSmoothing", left: 0f, right: 0.5f);
+ FloatField("movement.follower.slowdownTime", min: 0f);
+ FloatField("movement.stopDistance", min: 0f);
+ FloatField("movement.follower.leadInRadiusWhenApproachingDestination", min: 0f);
+ FloatField("movement.follower.desiredWallDistance", min: 0f);
+
+ if (PropertyField("managedState.enableGravity", "Gravity")) {
+ EditorGUI.indentLevel++;
+ PropertyField("movement.groundMask", "Raycast Ground Mask");
+ EditorGUI.indentLevel--;
+ }
+ var movementPlaneSource = FindProperty("movementPlaneSourceBacking");
+ PropertyField(movementPlaneSource, "Movement Plane Source");
+ if (AstarPath.active != null && AstarPath.active.data.graphs != null) {
+ var possiblySpherical = AstarPath.active.data.navmesh != null && !AstarPath.active.data.navmesh.RecalculateNormals;
+ if (!possiblySpherical && !movementPlaneSource.hasMultipleDifferentValues && (MovementPlaneSource)movementPlaneSource.intValue == MovementPlaneSource.Raycast) {
+ EditorGUILayout.HelpBox("Using raycasts as the movement plane source is only recommended if you have a spherical or otherwise non-planar world. It has a performance overhead.", MessageType.Info);
+ }
+ if (!possiblySpherical && !movementPlaneSource.hasMultipleDifferentValues && (MovementPlaneSource)movementPlaneSource.intValue == MovementPlaneSource.NavmeshNormal) {
+ EditorGUILayout.HelpBox("Using the navmesh normal as the movement plane source is only recommended if you have a spherical or otherwise non-planar world. It has a performance overhead.", MessageType.Info);
+ }
+ }
+
+ Section("Pathfinding");
+ PathfindingSettingsInspector();
+ AutoRepathInspector();
+
+
+ if (SectionEnableable("Local Avoidance", "managedState.enableLocalAvoidance")) {
+ if (Application.isPlaying && RVOSimulator.active == null && !EditorUtility.IsPersistent(target)) {
+ EditorGUILayout.HelpBox("There is no enabled RVOSimulator component in the scene. A single global RVOSimulator component is required for local avoidance.", MessageType.Warning);
+ }
+ FloatField("managedState.rvoSettings.agentTimeHorizon", min: 0f, max: 20.0f);
+ FloatField("managedState.rvoSettings.obstacleTimeHorizon", min: 0f, max: 20.0f);
+ PropertyField("managedState.rvoSettings.maxNeighbours");
+ ClampInt("managedState.rvoSettings.maxNeighbours", min: 0, max: SimulatorBurst.MaxNeighbourCount);
+ PropertyField("managedState.rvoSettings.layer");
+ PropertyField("managedState.rvoSettings.collidesWith");
+ Slider("managedState.rvoSettings.priority", left: 0f, right: 1.0f);
+ PropertyField("managedState.rvoSettings.locked");
+ }
+
+ Section("Debug");
+ PropertyField("movement.debugFlags", "Movement Debug Rendering");
+ PropertyField("managedState.rvoSettings.debug", "Local Avoidance Debug Rendering");
+ DebugInspector();
+
+ if (EditorGUI.EndChangeCheck()) {
+ for (int i = 0; i < targets.Length; i++) {
+ var script = targets[i] as FollowerEntity;
+ script.SyncWithEntity();
+ }
+ }
+ }
+ }
+}
+#else
+using UnityEditor;
+using UnityEngine;
+using Pathfinding.ECS;
+using UnityEditor.PackageManager;
+using UnityEditor.PackageManager.Requests;
+
+namespace Pathfinding {
+ // This inspector is only used if the Entities package is not installed
+ [CustomEditor(typeof(FollowerEntity), true)]
+ [CanEditMultipleObjects]
+ public class FollowerEntityEditor : EditorBase {
+ static AddRequest addRequest;
+
+ protected override void Inspector () {
+ if (addRequest != null) {
+ if (addRequest.Status == StatusCode.Success) {
+ addRequest = null;
+
+ // If we get this far, unity did not successfully reload the assemblies.
+ // Who knows what went wrong. Quite possibly restarting Unity will resolve the issue.
+ EditorUtility.DisplayDialog("Installed Entities package", "The entities package has been installed. You may have to restart the editor for changes to take effect.", "Ok");
+ } else if (addRequest.Status == StatusCode.Failure) {
+ EditorGUILayout.HelpBox("Failed to install the Entities package. Please install it manually using the Package Manager." + (addRequest.Error != null ? "\n" + addRequest.Error.message : ""), MessageType.Error);
+ } else {
+ EditorGUILayout.HelpBox("Installing entities package...", MessageType.None);
+ }
+ } else {
+ EditorGUILayout.HelpBox("This component requires the Entities package to be installed. Please install it using the Package Manager.", MessageType.Error);
+ if (GUILayout.Button("Install entities package")) {
+ addRequest = Client.Add("com.unity.entities");
+ }
+ }
+ }
+ }
+}
+#endif