Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System.Collections.Generic;
- using UnityEditor;
- using UnityEditor.SceneManagement;
- using UnityEngine;
- using Wax.Navigation;
- namespace Wax
- {
- public class WizardGenerateNavmesh : ScriptableWizard
- {
- private const float BOXCHECK_OFFSET = 0.05f;
- public Rect area;
- public float minSize = 1.0f, testHeight = 1.0f;
- public LayerMask obstacleLayerMask;
- private NavmeshGeneratorGizmos gizmoHandler;
- private List<Node> nodes;
- void OnWizardCreate()
- {
- gizmoHandler.Reset();
- Branch root = new Branch(GenerateNodes(area, gizmoHandler));
- AssignParents(root, null);
- Leaf[] leaves = root.GetLeaves();
- nodes = new List<Node>();
- foreach(Leaf leaf in leaves)
- {
- if(leaf.Occupied) continue;
- nodes.Add(new Node(leaf.Rect));
- }
- foreach(Node node in nodes)
- {
- node.SetNeighbours(FindNeighbours(node));
- }
- GameObject navmesh = new GameObject("Navmesh");
- navmesh.AddComponent<Navmesh>().SetNodes(nodes.ToArray());
- EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene());
- }
- void OnWizardUpdate()
- {
- if(gizmoHandler == null) return;
- gizmoHandler.SetBaseRect(area);
- gizmoHandler.Height = testHeight;
- }
- private INode[] GenerateNodes(Rect area, NavmeshGeneratorGizmos gizmoHandler)
- {
- Vector2 halfSize = area.size * 0.5f;
- Rect qi = new Rect(area.x + halfSize.x, area.y, halfSize.x, halfSize.y);
- Rect qii = new Rect(area.x, area.y, halfSize.x, halfSize.y);
- Rect qiii = new Rect(area.x, area.y + halfSize.y, halfSize.x, halfSize.y);
- Rect qiv = new Rect(area.x + halfSize.x, area.y + halfSize.y, halfSize.x, halfSize.y);
- //All of these rects are square, so there's no need to check width and height.
- INode[] nodes = new INode[4];
- bool occupied = Physics.CheckBox(new Vector3(qi.center.x, testHeight, qi.center.y), new Vector3(halfSize.x / 2 - BOXCHECK_OFFSET, 1, halfSize.y / 2 - BOXCHECK_OFFSET), Quaternion.identity, obstacleLayerMask);
- if (qi.width > minSize && occupied) nodes[0] = new Branch(GenerateNodes(qi, gizmoHandler));
- else
- {
- nodes[0] = new Leaf(qi, occupied);
- gizmoHandler.AddRect((Leaf)nodes[0]);
- }
- occupied = Physics.CheckBox(new Vector3(qii.center.x, testHeight, qii.center.y), new Vector3(halfSize.x / 2 - BOXCHECK_OFFSET, 1, halfSize.y / 2 - BOXCHECK_OFFSET), Quaternion.identity, obstacleLayerMask);
- if (qii.width > minSize && occupied) nodes[1] = new Branch(GenerateNodes(qii, gizmoHandler));
- else
- {
- nodes[1] = new Leaf(qii, occupied);
- gizmoHandler.AddRect((Leaf)nodes[1]);
- }
- occupied = Physics.CheckBox(new Vector3(qiii.center.x, testHeight, qiii.center.y), new Vector3(halfSize.x / 2 - BOXCHECK_OFFSET, 1, halfSize.y / 2 - BOXCHECK_OFFSET), Quaternion.identity, obstacleLayerMask);
- if (qiii.width > minSize && occupied) nodes[2] = new Branch(GenerateNodes(qiii, gizmoHandler));
- else
- {
- nodes[2] = new Leaf(qiii, occupied);
- gizmoHandler.AddRect((Leaf)nodes[2]);
- }
- occupied = Physics.CheckBox(new Vector3(qiv.center.x, testHeight, qiv.center.y), new Vector3(halfSize.x / 2 - BOXCHECK_OFFSET, 1, halfSize.y / 2 - BOXCHECK_OFFSET), Quaternion.identity, obstacleLayerMask);
- if (qiv.width > minSize && occupied) nodes[3] = new Branch(GenerateNodes(qiv, gizmoHandler));
- else
- {
- nodes[3] = new Leaf(qiv, occupied);
- gizmoHandler.AddRect((Leaf)nodes[3]);
- }
- return nodes;
- }
- private void AssignParents(INode node, Branch parent)
- {
- node.SetParent(parent);
- if(node is Branch)
- {
- foreach(INode child in ((Branch)node).Children)
- {
- AssignParents(child, (Branch)node);
- }
- }
- }
- private NavmeshGeneratorGizmos CreateGizmoHandler()
- {
- GameObject handler = new GameObject("Navmesh Generator Gizmos");
- handler.tag = "EditorOnly";
- return handler.AddComponent<NavmeshGeneratorGizmos>();
- }
- private Node[] FindNeighbours(Node node)
- {
- List<Node> neighbours = new List<Node>();
- foreach(Node other in nodes)
- {
- if(other == node) continue;
- Rect otherRect = other.Rect;
- Rect thisRect = node.Rect;
- //Difference check
- if(Mathf.Abs(otherRect.x + otherRect.width - thisRect.x) < float.Epsilon) neighbours.Add(other);
- else if(Mathf.Abs(thisRect.x + thisRect.width - otherRect.x) < float.Epsilon) neighbours.Add(other);
- else if(Mathf.Abs(otherRect.y + otherRect.height - thisRect.y) < float.Epsilon) neighbours.Add(other);
- else if(Mathf.Abs(thisRect.y + thisRect.height - otherRect.y) < float.Epsilon) neighbours.Add(other);
- }
- return neighbours.ToArray();
- }
- [MenuItem("Window/Navmesh Generator")]
- private static void Create()
- {
- WizardGenerateNavmesh wizard = DisplayWizard<WizardGenerateNavmesh>("Navmesh Generator", "Generate");
- wizard.gizmoHandler = FindObjectOfType<NavmeshGeneratorGizmos>();
- if (wizard.gizmoHandler == null) wizard.gizmoHandler = wizard.CreateGizmoHandler();
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement