using UnityEngine; using System; using System.Linq; using System.Threading; using System.IO; using System.Collections; using System.Collections.Generic; using WPM.PathFinding; namespace WPM { public partial class WorldMapGlobe : MonoBehaviour { #region Path Finding properties /// /// Fired when path finding algorithmn evaluates a cell. Return the increased cost for cell. /// public event PathFindingEvent OnPathFindingCrossCell; [SerializeField] HeuristicFormula _pathFindingHeuristicFormula = HeuristicFormula.SphericalDistance; /// /// The path finding heuristic formula to estimate distance from current position to destination /// public PathFinding.HeuristicFormula pathFindingHeuristicFormula { get { return _pathFindingHeuristicFormula; } set { if (value != _pathFindingHeuristicFormula) { _pathFindingHeuristicFormula = value; } } } [SerializeField] int _pathFindingSearchLimit = 2000; /// /// The maximum path length. /// public int pathFindingSearchLimit { get { return _pathFindingSearchLimit; } set { if (value != _pathFindingSearchLimit) { _pathFindingSearchLimit = value; } } } [SerializeField] int _pathFindingSearchMaxCost = 2000; /// /// The maximum cost for any path. /// public int pathFindingSearchMaxCost { get { return _pathFindingSearchMaxCost; } set { if (value != _pathFindingSearchMaxCost) { _pathFindingSearchMaxCost = value; isDirty = true; } } } #endregion #region Public API /// /// Returns an optimal path from startPosition to endPosition with options. /// /// The route consisting of a list of cell indexes. /// Start position in spherical coordinates /// End position in spherical coordinates /// Maximum search cost for the path finding algorithm. A value of 0 will use the global default defined by pathFindingMaxCost /// Specifies if hidden cells can be included /// Maximum crossing cost of path public List FindPath(Vector3 startPosition, Vector3 endPosition, int searchLimit = 0, bool includeStartingCell = false, HiddenCellsFilterMode hiddenCells = HiddenCellsFilterMode.OnlyUseVisibleCells, int searchMaxCost = 0) { int cellStartIndex = GetCellIndex(startPosition); int cellEndIndex = GetCellIndex(endPosition); return FindPath(cellStartIndex, cellEndIndex, searchLimit, includeStartingCell, hiddenCells, searchMaxCost); } /// /// Returns an optimal path from startPosition to endPosition with options. /// /// The route consisting of a list of cell indexes. /// Index of starting cell /// Index of destination cell /// Maximum search cost for the path finding algorithm. A value of 0 will use the global default defined by pathFindingMaxCost /// Specifies if hidden cells can be included /// Maximum crossing cost of path public List FindPath(int cellIndexStart, int cellIndexEnd, int searchLimit = 0, bool includeStartingCell = false, HiddenCellsFilterMode hiddenCells = HiddenCellsFilterMode.OnlyUseVisibleCells, int searchMaxCost = 0) { if (shouldGenerateGrid) { GenerateGrid(); } if (cellIndexStart < 0 || cells == null || cellIndexStart >= cells.Length || cellIndexEnd < 0 || cellIndexEnd >= cells.Length) return null; int startingPoint = cellIndexStart; int endingPoint = cellIndexEnd; List routePoints = null; // Minimum distance for routing? if (startingPoint != endingPoint) { ComputeRouteMatrix(); finder.Formula = _pathFindingHeuristicFormula; finder.SearchLimit = searchLimit == 0 ? _pathFindingSearchLimit : searchLimit; finder.HiddenCellsFilter = hiddenCells; finder.SearchMaxCost = searchMaxCost == 0 ? _pathFindingSearchMaxCost : searchMaxCost; if (OnPathFindingCrossCell != null) { finder.OnCellCross = FindRoutePositionValidator; } else { finder.OnCellCross = null; } List route = finder.FindPath(startingPoint, endingPoint); if (route != null) { int count = route.Count; routePoints = new List(count); int last = includeStartingCell ? count - 1 : count - 2; for (int r = last; r >= 0; r--) { routePoints.Add(route[r].index); } if (count == 0 || routePoints[routePoints.Count - 1] != cellIndexEnd) { routePoints.Add(cellIndexEnd); } } else { return null; // no route available } } return routePoints; } /// /// Sets if path finding can cross this cell. /// public bool SetCellCanCross(int cellIndex, bool canCross) { if (cellIndex < 0 || cellIndex >= cells.Length) return false; cells[cellIndex].canCross = canCross; return true; } /// /// Returns whether path finding can cross this cell. /// public bool GetCellCanCross(int cellIndex) { if (cellIndex < 0 || cellIndex >= cells.Length) return false; return cells[cellIndex].canCross; } /// /// Sets the cost for crossing a given cell side. Note that the cost is only assigned in one direction (from this cell to the outside). /// /// true, if neighbour cost was set, false otherwise. /// Cell index. /// Cell neighbour index. /// Cost. /// If set to true, cost is assigned in either direction. public bool SetCellNeighbourCost(int cellIndex, int cellNeighbourIndex, int cost, bool bothSides = true) { if (cells == null || cellIndex < 0 || cellIndex >= cells.Length) return false; Cell cell = cells[cellIndex]; int neighbourIndex = GetCellNeighbourIndex(cellIndex, cellNeighbourIndex); if (neighbourIndex < 0) return false; cell.neighboursCosts[neighbourIndex] = cost; if (bothSides) { cell = cells[cellNeighbourIndex]; neighbourIndex = GetCellNeighbourIndex(cellNeighbourIndex, cellIndex); if (neighbourIndex < 0) return false; cell.neighboursCosts[neighbourIndex] = cost; } return true; } /// /// Sets the cost for crossing any cell side. Note that the cost is only assigned in one direction (from this cell to the outside). /// public void SetCellNeighboursCost(int cellIndex, int cost, bool bothSides = true) { if (cells == null || cellIndex < 0 || cellIndex >= cells.Length) return; Cell cell = cells[cellIndex]; int neighbourCount = cell.neighboursIndices.Length; for (int k = 0; k < neighbourCount; k++) { SetCellNeighbourCost(cellIndex, cell.neighboursIndices[k], cost, bothSides); } } /// /// Gets the cost for crossing a given cell side /// public int GetCellNeighbourCost(int cellIndex, int neighbourIndex) { if (cells == null || cellIndex < 0 || cellIndex >= cells.Length) return -1; Cell cell = cells[cellIndex]; if (neighbourIndex < 0 || neighbourIndex >= cell.neighboursCosts.Length) { return -1; } return cell.neighboursCosts[neighbourIndex]; } #endregion } }