diff options
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.cs | 224 |
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 |