private static bool DrawSubGridHandle(SubGrid subGrid, SubGrid activeSubGrid, Color subGridColor) { Vector2Int subGridOriginPosition = subGrid.GetOriginCoordinate(); Vector3 subGridWorldPosition = subGrid.GetNavGrid().GetOriginWorldPosition() + new Vector3(subGridOriginPosition.x, 0, subGridOriginPosition.y); Vector3[] vertexs = { subGridWorldPosition, //Bottom-Left subGridWorldPosition + new Vector3(subGrid.Width, 0, 0), //Bottom-Right subGridWorldPosition + new Vector3(subGrid.Width, 0, subGrid.Height), //Top-Right subGridWorldPosition + new Vector3(0, 0, subGrid.Height) //Top-Left }; Handles.DrawSolidRectangleWithOutline(vertexs, subGridColor, Color.black); if (subGrid.Equals(activeSubGrid)) { return(false); } float centerX = vertexs[0].x + ((vertexs[1].x - vertexs[0].x) / 2f); float centerZ = vertexs[0].z + ((vertexs[3].z - vertexs[0].z) / 2f); Vector3 centerPosition = new Vector3(centerX, vertexs[0].y, centerZ); float buttonSize = 6f; if (Handles.Button(centerPosition, Quaternion.LookRotation(Vector3.up), buttonSize, buttonSize, Handles.RectangleHandleCap)) { return(true); } return(false); }
private static void HandleNodeClick(SubGrid subGrid, Vector2Int nodeCoordinates) { //Get the active instance of NavGridTool and send it the NodeClick NavGridTool navGridTool = (EditorWindow.GetWindow(typeof(NavGridTool)) as NavGridTool); navGridTool.HandleNodeClick(nodeCoordinates); }
public void DrawSubGrid(NavGridTool tool) { if (currentMode != Mode.EDIT) { return; } SubGrid selectedSubGrid = tool.SelectedSubGrid; List <SubGrid> subGrids = selectedSubGrid.GetChildSubGrids(); //If the current SubGrid has child SubGrids if (subGrids.Count > 0) { DrawSubGridHandle(selectedSubGrid, selectedSubGrid, SUBGRID_COLOR); for (int i = 0; i < subGrids.Count; i++) { if (DrawSubGridHandle(subGrids[i], selectedSubGrid, SUBGRID_COLOR)) { tool.SelectChildSubGrid(i); return; } } } else { DrawNodeHandles(tool, selectedSubGrid); } }
//Splits the NavGrid into SubGrids for display purposes //This is needed as drawing too many Handles at once slows down the editor public static SubGrid CreateSubGrids(NavGrid navGrid, int nodeRenderLimit) { SubGrid primarySubGrid = new SubGrid(navGrid, null, new Vector2Int(), navGrid.Width, navGrid.Height); GenerateSubGrids(primarySubGrid, navGrid, nodeRenderLimit); return(primarySubGrid); }
public void SelectChildSubGrid(int index) { if (index >= 0 && index < _selectedSubGrid.GetChildSubGrids().Count) { _selectedSubGrid = _selectedSubGrid.GetChildSubGrids()[index]; } SceneView.RepaintAll(); }
public void RegenerateSubGrids() { if (currentNavGrid) { _selectedSubGrid = SubGridGenerator.CreateSubGrids(currentNavGrid, NODE_RENDER_LIMIT); _selectedNode = NavGrid.NO_NODE; SceneView.RepaintAll(); } }
public SubGrid(NavGrid navGrid, SubGrid parent, Vector2Int originCoordinate, int width, int height) { this.navGrid = navGrid; this.parent = parent; this.originCoordinate = originCoordinate; this.width = width; this.height = height; subGrids = new List <SubGrid>(); }
//Divides the provided subgrid using the provided devisions private static List <SubGrid> DivideSubGrid(SubGrid currentSubGrid, NavGrid navGrid, Vector2 divisions) { int width = currentSubGrid.Width; int height = currentSubGrid.Height; List <SubGrid> newSubGrids = new List <SubGrid>(); float widthDivisions = divisions.x; float heightDivisions = divisions.y; Vector2Int originCoordinate = currentSubGrid.GetOriginCoordinate(); Vector2Int currentCoordinate = originCoordinate; int xSize = Mathf.CeilToInt(width / widthDivisions); int ySize = Mathf.CeilToInt(height / heightDivisions); for (int y = 0; y < heightDivisions; y++) { //Correct ySize on the final row if (y == heightDivisions - 1) { ySize = height - Mathf.RoundToInt(currentCoordinate.y - originCoordinate.y); } currentCoordinate.x = originCoordinate.x; for (int x = 0; x < widthDivisions; x++) { SubGrid newSubGrid; //Correct xSize on the final column if (x == widthDivisions - 1) { newSubGrid = new SubGrid(navGrid, currentSubGrid, currentCoordinate, width - Mathf.RoundToInt(currentCoordinate.x - originCoordinate.x), ySize); } else { newSubGrid = new SubGrid(navGrid, currentSubGrid, currentCoordinate, xSize, ySize); } currentSubGrid.AddChildSubGrid(newSubGrid); newSubGrids.Add(newSubGrid); currentCoordinate.x += xSize; } currentCoordinate.y += ySize; } return(newSubGrids); }
//Calculates how many times each side of the grid will be divided private static Vector2 CalculateGridDivisions(SubGrid subGrid, int targetNumberOfSections, int maxHandlesPerFrame) { int width = subGrid.Width; int height = subGrid.Height; //If we only need 2 sections, divide the longest side if (targetNumberOfSections == 2) { if (width > height) { return(new Vector2(2, 1)); } else { return(new Vector2(1, 2)); } } else { Vector2 gridDivisions = new Vector2(); int divisor = Mathf.CeilToInt(Mathf.Sqrt(targetNumberOfSections)); //Calculate the shortest side first if (width < height) { gridDivisions.x = CalculateSideDivisions(width, divisor, maxHandlesPerFrame); //Calculate how many divisions are needed for the other side if (gridDivisions.x != divisor) { divisor = Mathf.CeilToInt((targetNumberOfSections / (float)gridDivisions.x)); } gridDivisions.y = Mathf.CeilToInt(targetNumberOfSections / gridDivisions.x); } else { gridDivisions.y = CalculateSideDivisions(height, divisor, maxHandlesPerFrame); //Calculate how many divisions are needed for the other side if (gridDivisions.y != divisor) { divisor = Mathf.CeilToInt((targetNumberOfSections / (float)gridDivisions.y)); } gridDivisions.x = Mathf.CeilToInt(targetNumberOfSections / gridDivisions.y); } return(gridDivisions); } }
public void CreateSubGridAtSelection() { if (SelectedNode.Equals(NavGrid.NO_NODE)) { return; } Vector2Int point = _selectedNode; point.x = Mathf.Clamp(point.x - (_selectedSubGrid.Width / 2), 0, currentNavGrid.Width - 1); point.y = Mathf.Clamp(point.y - (_selectedSubGrid.Height / 2), 0, currentNavGrid.Height - 1); _selectedSubGrid = SubGridGenerator.CreateSubGridAtPoint(currentNavGrid, _selectedSubGrid, point, _NODE_RENDER_LIMIT); SceneView.RepaintAll(); }
public void SelectParentSubGrid() { if (_selectedSubGrid == null || _selectedSubGrid.GetParentSubGrid() == null) { return; } SubGrid parentSubGrid = _selectedSubGrid.GetParentSubGrid(); if (parentSubGrid != null) { _selectedSubGrid = parentSubGrid; } SceneView.RepaintAll(); }
//Fires when the active scene object changes private void OnSelectionChange() { currentNavGrid = FindSelectedNavGrid(); if (currentNavGrid) { SceneView.onSceneGUIDelegate -= OnSceneGUI; SceneView.onSceneGUIDelegate += OnSceneGUI; _selectedSubGrid = SubGridGenerator.CreateSubGrids(currentNavGrid, NODE_RENDER_LIMIT); } else { SceneView.onSceneGUIDelegate -= OnSceneGUI; } }
public static SubGrid CreateSubGridAtPoint(NavGrid navgrid, SubGrid currentSubgrid, Vector2Int point, int nodeRenderLimit) { int width = Mathf.FloorToInt(Mathf.Sqrt(nodeRenderLimit)); int height = width; if (navgrid.Width < point.x + width) { width = navgrid.Width - point.x; } if (navgrid.Height < point.y + height) { height = navgrid.Height - point.y; } SubGrid newSubGrid = new SubGrid(navgrid, currentSubgrid, point, width, height); return(newSubGrid); }
//Recursively divides the provided subgrid into smaller subgrids until acceptable sizes are reached private static void GenerateSubGrids(SubGrid subGrid, NavGrid navGrid, int maxHandlesPerFrame) { //Determine how many sections we will be dividing into int numberOfSections = CalculateTargetNumberOfSections(subGrid, maxHandlesPerFrame); if (numberOfSections == 1) { return; } //Calculate how we will be dividing the grid, avoiding creating side lengths that are too small Vector2 gridDivisors = CalculateGridDivisions(subGrid, numberOfSections, maxHandlesPerFrame); //Divide the grid into SubGrids List <SubGrid> newSubGrids = DivideSubGrid(subGrid, navGrid, gridDivisors); //Divide each newly generated SubGrid foreach (SubGrid newSubGrid in newSubGrids) { GenerateSubGrids(newSubGrid, navGrid, maxHandlesPerFrame); } }
//Calculate how many sections the grid should be divided into private static int CalculateTargetNumberOfSections(SubGrid subGrid, int maxHandlesPerFrame) { float targetAmount = (subGrid.Width * subGrid.Height) / (float)maxHandlesPerFrame; if (targetAmount <= 1f) { return(1); } if (targetAmount <= 2f) { return(2); } if (targetAmount <= 4) { return(4); } if (targetAmount <= 9f) { return(9); } if (targetAmount <= 16f) { return(16); } if (targetAmount <= 25f) { return(25); } return(36); }
private void DrawNodeHandles(NavGridTool tool, SubGrid subGrid) { float NODE_SIZE = 0.45f; NavGrid navGrid = subGrid.GetNavGrid(); Vector2Int subGridOriginPosition = subGrid.GetOriginCoordinate(); Vector3 subGridWorldPosition = navGrid.GetOriginWorldPosition() + new Vector3(subGridOriginPosition.x, 0, subGridOriginPosition.y); int width = subGrid.Width; int height = subGrid.Height; //Draw each node for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { Vector2Int nodeCoordinates = new Vector2Int( subGridOriginPosition.x + x, subGridOriginPosition.y + y ); Handles.color = tool.ChooseNodeColor(nodeCoordinates); if (currentMode == Mode.EDIT) { //Draw nodes as buttons and watch for input if (Handles.Button(subGridWorldPosition + new Vector3(x, 0, y), Quaternion.LookRotation(Vector3.up), NODE_SIZE, NODE_SIZE, Handles.CubeHandleCap)) { HandleNodeClick(subGrid, nodeCoordinates); } } } } }
public void AddChildSubGrid(SubGrid newGrid) { subGrids.Add(newGrid); }