diff options
Diffstat (limited to 'Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Editor/RuleEditors')
10 files changed, 337 insertions, 0 deletions
diff --git a/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Editor/RuleEditors/GridGraphRuleEditor.cs b/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Editor/RuleEditors/GridGraphRuleEditor.cs new file mode 100644 index 0000000..a4f941c --- /dev/null +++ b/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Editor/RuleEditors/GridGraphRuleEditor.cs @@ -0,0 +1,7 @@ +namespace Pathfinding.Graphs.Grid.Rules { + /// <summary>Common interface for all grid graph rule editors</summary> + public interface IGridGraphRuleEditor { + void OnInspectorGUI(GridGraph graph, GridGraphRule rule); + void OnSceneGUI(GridGraph graph, GridGraphRule rule); + } +} diff --git a/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Editor/RuleEditors/GridGraphRuleEditor.cs.meta b/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Editor/RuleEditors/GridGraphRuleEditor.cs.meta new file mode 100644 index 0000000..f05cd6d --- /dev/null +++ b/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Editor/RuleEditors/GridGraphRuleEditor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6cb8fa407b3b048b0976573f12ca770e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Editor/RuleEditors/RuleAnglePenaltyEditor.cs b/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Editor/RuleEditors/RuleAnglePenaltyEditor.cs new file mode 100644 index 0000000..ba3b721 --- /dev/null +++ b/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Editor/RuleEditors/RuleAnglePenaltyEditor.cs @@ -0,0 +1,22 @@ +using Pathfinding.Graphs.Grid.Rules; +using UnityEditor; +using UnityEngine; + +namespace Pathfinding { + /// <summary>Editor for the <see cref="RuleAnglePenalty"/> rule</summary> + [CustomGridGraphRuleEditor(typeof(RuleAnglePenalty), "Penalty from Slope Angle")] + public class RuleAnglePenaltyEditor : IGridGraphRuleEditor { + public void OnInspectorGUI (GridGraph graph, GridGraphRule rule) { + var target = rule as RuleAnglePenalty; + + if (target.curve == null || target.curve.length == 0) target.curve = AnimationCurve.Linear(0, 0, 90, 1); + target.penaltyScale = EditorGUILayout.FloatField("Penalty Scale", target.penaltyScale); + if (target.penaltyScale < 1) target.penaltyScale = 1; + target.curve = EditorGUILayout.CurveField(target.curve, Color.red, new Rect(0, 0, 90, 1)); + + EditorGUILayout.HelpBox("Nodes will get a penalty between 0 and " + target.penaltyScale.ToString("0") + " depending on the slope angle", MessageType.None); + } + + public void OnSceneGUI (GridGraph graph, GridGraphRule rule) { } + } +} diff --git a/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Editor/RuleEditors/RuleAnglePenaltyEditor.cs.meta b/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Editor/RuleEditors/RuleAnglePenaltyEditor.cs.meta new file mode 100644 index 0000000..130c50d --- /dev/null +++ b/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Editor/RuleEditors/RuleAnglePenaltyEditor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2b43f06d7cb7e494b901c3ae81026332 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Editor/RuleEditors/RuleElevationPenaltyEditor.cs b/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Editor/RuleEditors/RuleElevationPenaltyEditor.cs new file mode 100644 index 0000000..30eac85 --- /dev/null +++ b/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Editor/RuleEditors/RuleElevationPenaltyEditor.cs @@ -0,0 +1,61 @@ +using Pathfinding.Graphs.Grid.Rules; +using UnityEditor; +using UnityEngine; + +namespace Pathfinding { + /// <summary>Editor for the <see cref="RuleElevationPenalty"/> rule</summary> + [CustomGridGraphRuleEditor(typeof(RuleElevationPenalty), "Penalty from Elevation")] + public class RuleElevationPenaltyEditor : IGridGraphRuleEditor { + float lastChangedTime = -10000; + + public void OnInspectorGUI (GridGraph graph, GridGraphRule rule) { + var target = rule as RuleElevationPenalty; + + if (target.curve == null || target.curve.length == 0) target.curve = AnimationCurve.Linear(0, 0, 1, 1); + target.penaltyScale = EditorGUILayout.FloatField("Penalty Scale", target.penaltyScale); + target.penaltyScale = Mathf.Max(target.penaltyScale, 1.0f); + + EditorGUILayout.LabelField("Elevation Range", ""); + EditorGUI.BeginChangeCheck(); + EditorGUI.indentLevel++; + target.elevationRange.x = EditorGUILayout.FloatField("Min", target.elevationRange.x); + target.elevationRange.y = EditorGUILayout.FloatField("Max", target.elevationRange.y); + target.elevationRange.x = Mathf.Max(target.elevationRange.x, 0); + target.elevationRange.y = Mathf.Max(target.elevationRange.y, target.elevationRange.x + 1.0f); + EditorGUI.indentLevel--; + if (EditorGUI.EndChangeCheck()) lastChangedTime = Time.realtimeSinceStartup; + + target.curve = EditorGUILayout.CurveField(target.curve, Color.red, new Rect(0, 0, 1, 1)); + + EditorGUILayout.HelpBox("Nodes will get a penalty between 0 and " + target.penaltyScale.ToString("0") + " depending on their elevation above the grid graph plane", MessageType.None); + } + + protected static readonly Color GizmoColorMax = new Color(222.0f/255, 113.0f/255, 33.0f/255, 0.5f); + protected static readonly Color GizmoColorMin = new Color(33.0f/255, 104.0f/255, 222.0f/255, 0.5f); + + public void OnSceneGUI (GridGraph graph, GridGraphRule rule) { + var target = rule as RuleElevationPenalty; + + // Draw some helpful gizmos in the scene view for a few seconds whenever the settings change + const float FullAlphaTime = 2.0f; + const float FadeoutTime = 0.5f; + float alpha = Mathf.SmoothStep(1, 0, (Time.realtimeSinceStartup - lastChangedTime - FullAlphaTime)/FadeoutTime); + + if (alpha <= 0) return; + + var currentTransform = graph.transform * Matrix4x4.Scale(new Vector3(graph.width, 1, graph.depth)); + Handles.matrix = currentTransform.matrix; + var zTest = Handles.zTest; + Handles.zTest = UnityEngine.Rendering.CompareFunction.LessEqual; + Handles.color = GizmoColorMin * new Color(1.0f, 1.0f, 1.0f, alpha); + Handles.DrawAAConvexPolygon(new Vector3[] { new Vector3(0, target.elevationRange.x, 0), new Vector3(1, target.elevationRange.x, 0), new Vector3(1, target.elevationRange.x, 1), new Vector3(0, target.elevationRange.x, 1) }); + Handles.color = GizmoColorMax * new Color(1.0f, 1.0f, 1.0f, alpha); + Handles.DrawAAConvexPolygon(new Vector3[] { new Vector3(0, target.elevationRange.y, 0), new Vector3(1, target.elevationRange.y, 0), new Vector3(1, target.elevationRange.y, 1), new Vector3(0, target.elevationRange.y, 1) }); + Handles.zTest = zTest; + Handles.matrix = Matrix4x4.identity; + + // Repaint the scene view until the alpha goes to zero + SceneView.RepaintAll(); + } + } +} diff --git a/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Editor/RuleEditors/RuleElevationPenaltyEditor.cs.meta b/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Editor/RuleEditors/RuleElevationPenaltyEditor.cs.meta new file mode 100644 index 0000000..4778db3 --- /dev/null +++ b/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Editor/RuleEditors/RuleElevationPenaltyEditor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bb9fce5dbc8cd4af78db90d7e4f661ac +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Editor/RuleEditors/RulePerLayerModificationsEditor.cs b/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Editor/RuleEditors/RulePerLayerModificationsEditor.cs new file mode 100644 index 0000000..82fb808 --- /dev/null +++ b/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Editor/RuleEditors/RulePerLayerModificationsEditor.cs @@ -0,0 +1,49 @@ +using UnityEditor; +using UnityEngine; +using System.Linq; +using Pathfinding.Graphs.Grid.Rules; + +namespace Pathfinding { + /// <summary>Editor for the <see cref="RulePerLayerModifications"/> rule</summary> + [CustomGridGraphRuleEditor(typeof(RulePerLayerModifications), "Per Layer Modifications")] + public class RulePerLayerModificationsEditor : IGridGraphRuleEditor { + public void OnInspectorGUI (GridGraph graph, GridGraphRule rule) { + var target = rule as RulePerLayerModifications; + + for (int i = 0; i < target.layerRules.Length; i++) { + GUILayout.BeginHorizontal(); + target.layerRules[i].layer = EditorGUILayout.LayerField((int)target.layerRules[i].layer); + target.layerRules[i].action = (RulePerLayerModifications.RuleAction)EditorGUILayout.EnumPopup(target.layerRules[i].action); + if (target.layerRules[i].action == RulePerLayerModifications.RuleAction.SetTag) { + target.layerRules[i].tag = Pathfinding.Util.EditorGUILayoutHelper.TagField(new GUIContent(""), target.layerRules[i].tag, AstarPathEditor.EditTags); + } else { + EditorGUILayout.LabelField(""); + } + if (GUILayout.Button("", AstarPathEditor.astarSkin.FindStyle("SimpleDeleteButton"))) { + var ls = target.layerRules.ToList(); + ls.RemoveAt(i); + target.layerRules = ls.ToArray(); + } + GUILayout.Space(5); + GUILayout.EndHorizontal(); + } + + GUILayout.BeginHorizontal(); + GUILayout.Space(32); + if (GUILayout.Button("Add per layer rule", GUILayout.MaxWidth(160))) { + var ls = target.layerRules.ToList(); + ls.Add(new RulePerLayerModifications.PerLayerRule()); + target.layerRules = ls.ToArray(); + } + GUILayout.EndHorizontal(); + + if (graph.collision.use2D) { + EditorGUILayout.HelpBox("This rule does not work with 2D physics, since it requires height testing information", MessageType.Error); + } else if (!graph.collision.heightCheck) { + EditorGUILayout.HelpBox("This rule requires height testing to be enabled on the grid graph", MessageType.Error); + } + } + + public void OnSceneGUI (GridGraph graph, GridGraphRule rule) { } + } +} diff --git a/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Editor/RuleEditors/RulePerLayerModificationsEditor.cs.meta b/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Editor/RuleEditors/RulePerLayerModificationsEditor.cs.meta new file mode 100644 index 0000000..bc4a0be --- /dev/null +++ b/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Editor/RuleEditors/RulePerLayerModificationsEditor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e94be22ba4fbd41daac01121acf6110a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Editor/RuleEditors/RuleTextureEditor.cs b/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Editor/RuleEditors/RuleTextureEditor.cs new file mode 100644 index 0000000..3081eb7 --- /dev/null +++ b/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Editor/RuleEditors/RuleTextureEditor.cs @@ -0,0 +1,143 @@ +using Pathfinding.Graphs.Grid.Rules; +using UnityEditor; +using UnityEngine; + +namespace Pathfinding { + /// <summary>Editor for the <see cref="RuleTexture"/> rule</summary> + [CustomGridGraphRuleEditor(typeof(RuleTexture), "Texture")] + public class RuleTextureEditor : IGridGraphRuleEditor { + protected static readonly string[] ChannelUseNames = { "None", "Penalty", "Height", "Walkability and Penalty", "Walkability" }; + + public void OnInspectorGUI (GridGraph graph, GridGraphRule rule) { + var target = rule as RuleTexture; + + target.texture = GraphEditor.ObjectField(new GUIContent("Texture"), target.texture, typeof(Texture2D), false, true) as Texture2D; + + GUILayout.BeginHorizontal(); + GUILayout.FlexibleSpace(); + if (GUILayout.Button("Generate Reference")) { + SaveReferenceTexture(graph); + EditorUtility.DisplayDialog("Reference texture saved", "A texture has been saved in which every pixel corresponds to one node. The red channel represents if a node is walkable or not. The green channel represents the (normalized) Y coordinate of the nodes.", "Ok"); + } + GUILayout.EndHorizontal(); + + if (target.texture != null) { + string path = AssetDatabase.GetAssetPath(target.texture); + + if (path != "") { + var importer = AssetImporter.GetAtPath(path) as TextureImporter; + if (importer != null && !importer.isReadable) { + if (GraphEditor.FixLabel("Texture is not readable")) { + importer.isReadable = true; + EditorUtility.SetDirty(importer); + AssetDatabase.ImportAsset(path); + } + } + } + } + + target.scalingMode = (RuleTexture.ScalingMode)EditorGUILayout.EnumPopup("Scaling Mode", target.scalingMode); + if (target.scalingMode == RuleTexture.ScalingMode.FixedScale) { + EditorGUI.indentLevel++; + target.nodesPerPixel = EditorGUILayout.FloatField("Nodes Per Pixel", target.nodesPerPixel); + EditorGUI.indentLevel--; + } + + for (int i = 0; i < 4; i++) { + char channelName = "RGBA"[i]; + target.channels[i] = (RuleTexture.ChannelUse)EditorGUILayout.Popup("" + channelName, (int)target.channels[i], ChannelUseNames); + + if (target.channels[i] != RuleTexture.ChannelUse.None) { + EditorGUI.indentLevel++; + if (target.channels[i] != RuleTexture.ChannelUse.Walkable) { + target.channelScales[i] = EditorGUILayout.FloatField("Scale", target.channelScales[i]); + } + + string help = ""; + switch (target.channels[i]) { + case RuleTexture.ChannelUse.Penalty: + help = "Penalty goes from 0 to " + target.channelScales[i].ToString("0") + " depending on the " + channelName + " channel value"; + break; + case RuleTexture.ChannelUse.Position: + help = "Nodes will have their Y coordinate set to a value between 0 and " + target.channelScales[i].ToString("0") + " depending on the "+channelName+" channel"; + + if (graph.collision.heightCheck) { + EditorGUILayout.HelpBox("Height testing is enabled but the node positions will be overwritten by the texture data. You should disable either height testing or this feature.", MessageType.Error); + } + break; + case RuleTexture.ChannelUse.WalkablePenalty: + help = "If the "+channelName+" channel is 0, the node is made unwalkable. Otherwise the penalty goes from 0 to " + target.channelScales[i].ToString("0") + " depending on the " + channelName + " channel value"; + break; + case RuleTexture.ChannelUse.Walkable: + help = "If the "+channelName+" channel is 0, the node is made unwalkable."; + break; + } + + EditorGUILayout.HelpBox(help, MessageType.None); + + if ((target.channels[i] == RuleTexture.ChannelUse.Penalty || target.channels[i] == RuleTexture.ChannelUse.WalkablePenalty) && target.channelScales[i] < 0) { + EditorGUILayout.HelpBox("Negative penalties are not supported. You can instead raise the penalty of other nodes.", MessageType.Error); + } + + EditorGUI.indentLevel--; + } + } + } + + static void SaveReferenceTexture (GridGraph graph) { + if (graph.nodes == null || graph.nodes.Length != graph.width * graph.depth * graph.LayerCount) { + AstarPath.active.Scan(); + } + + if (graph.nodes.Length < graph.width * graph.depth) { + Debug.LogError("Couldn't create reference image since nodes.Length < width*depth"); + return; + } + + if (graph.nodes.Length == 0) { + Debug.LogError("Couldn't create reference image since the graph is too small (0*0)"); + return; + } + + if (graph.LayerCount > 1) { + Debug.LogWarning("Creating reference image for a layered grid graph. Only the first layer will be included in the image."); + } + + var tex = new Texture2D(graph.width, graph.depth); + + float maxY = float.NegativeInfinity; + for (int i = 0; i < graph.nodes.Length; i++) { + Vector3 p = graph.nodes[i] != null? graph.transform.InverseTransform((Vector3)graph.nodes[i].position) : Vector3.zero; + maxY = p.y > maxY ? p.y : maxY; + } + + var cols = new Color[graph.width*graph.depth]; + + for (int z = 0; z < graph.depth; z++) { + for (int x = 0; x < graph.width; x++) { + GraphNode node = graph.nodes[z*graph.width+x]; + if (node != null) { + float v = node.Walkable ? 1F : 0.0F; + Vector3 p = graph.transform.InverseTransform((Vector3)node.position); + float q = p.y / maxY; + cols[z*graph.width+x] = new Color(v, q, 0); + } else { + cols[z*graph.width+x] = new Color(0, 0, 0); + } + } + } + tex.SetPixels(cols); + tex.Apply(); + + string path = AssetDatabase.GenerateUniqueAssetPath("Assets/gridReference.png"); + System.IO.File.WriteAllBytes(path, tex.EncodeToPNG()); + + AssetDatabase.Refresh(); + Object obj = AssetDatabase.LoadAssetAtPath(path, typeof(Texture)); + + EditorGUIUtility.PingObject(obj); + } + + public void OnSceneGUI (GridGraph graph, GridGraphRule rule) { } + } +} diff --git a/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Editor/RuleEditors/RuleTextureEditor.cs.meta b/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Editor/RuleEditors/RuleTextureEditor.cs.meta new file mode 100644 index 0000000..3bd7887 --- /dev/null +++ b/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Editor/RuleEditors/RuleTextureEditor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 50639ba8f5afa4626889b9ef9d6e5ab4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: |