// test if cell is neighbour of previous cell
 private bool ValidateDrag(HexCell newCell)
 {
     for (dragDirection = HexDirection.NE; dragDirection <= HexDirection.NW; dragDirection++)
     {
         if (previousCell.GetNeighbour(dragDirection) == newCell)
         {
             return(true);
         }
     }
     return(false);
 }
        private bool IsErodible(HexCell cell)
        {
            var erodibleElevation = cell.Elevation - 2;

            for (var d = HexDirection.NE; d <= HexDirection.NW; d++)
            {
                var neighbour = cell.GetNeighbour(d);
                if (neighbour && neighbour.Elevation <= erodibleElevation)
                {
                    return(true);
                }
            }
            return(false);
        }
        private void TriangulateWater(HexDirection direction, HexCell cell, Vector3 centre)
        {
            centre.y = cell.WaterSurfaceY;
            var neighbour = cell.GetNeighbour(direction);

            if (neighbour != null && !neighbour.IsUnderwater)
            {
                TriangulateWaterShore(direction, cell, neighbour, centre);
            }
            else
            {
                TriangulateOpenWater(direction, cell, neighbour, centre);
            }
        }
        private HexCell GetErosionTarget(HexCell cell)
        {
            var candidates = ListPool <HexCell> .Get();

            var erodibleElevation = cell.Elevation - 2;

            for (var d = HexDirection.NE; d <= HexDirection.NW; d++)
            {
                var neighbour = cell.GetNeighbour(d);
                if (neighbour && neighbour.Elevation <= erodibleElevation)
                {
                    candidates.Add(neighbour);
                }
            }

            var candidate = candidates[Random.Range(0, candidates.Count)];

            ListPool <HexCell> .Add(candidates);

            return(candidate);
        }
        private void TriangulateOpenWater(HexDirection direction, HexCell cell, HexCell neighbour, Vector3 centre)
        {
            var c1 = centre + HexMetrics.GetFirstWaterCorner(direction);
            var c2 = centre + HexMetrics.GetSecondWaterCorner(direction);

            Water.AddTriangle(centre, c1, c2);
            var indices = new Vector3(cell.Index, cell.Index, cell.Index);

            Water.AddTriangleCellData(indices, weights1);

            if (neighbour == null || direction > HexDirection.SE)
            {
                return;
            }

            var bridge = HexMetrics.GetWaterBridge(direction);
            var e1     = c1 + bridge;
            var e2     = c2 + bridge;

            Water.AddQuad(c1, c2, e1, e2);
            indices.y = neighbour.Index;
            Water.AddQuadCellData(indices, weights1, weights2);

            if (direction > HexDirection.E)
            {
                return;
            }

            var nextNeighbour = cell.GetNeighbour(direction.Next());

            if (nextNeighbour == null || !nextNeighbour.IsUnderwater)
            {
                return;
            }

            Water.AddTriangle(c2, e2, c2 + HexMetrics.GetWaterBridge(direction.Next()));
            indices.z = nextNeighbour.Index;
            Water.AddTriangleCellData(indices, weights1, weights2, weights3);
        }
        private void TriangulateWaterShore(HexDirection direction, HexCell cell, HexCell neighbour, Vector3 centre)
        {
            var e1 = new EdgeVertices(
                centre + HexMetrics.GetFirstWaterCorner(direction),
                centre + HexMetrics.GetSecondWaterCorner(direction)
                );

            Water.AddTriangle(centre, e1.v1, e1.v2);
            Water.AddTriangle(centre, e1.v2, e1.v3);
            Water.AddTriangle(centre, e1.v3, e1.v4);
            Water.AddTriangle(centre, e1.v4, e1.v5);

            var indices = new Vector3(cell.Index, neighbour.Index, cell.Index);

            Water.AddTriangleCellData(indices, weights1);
            Water.AddTriangleCellData(indices, weights1);
            Water.AddTriangleCellData(indices, weights1);
            Water.AddTriangleCellData(indices, weights1);

            var centre2 = neighbour.Position;

            if (neighbour.ColumnIndex < cell.ColumnIndex - 1)
            {
                centre2.x += HexMetrics.WrapSize * HexMetrics.InnerDiameter;
            }
            else if (neighbour.ColumnIndex > cell.ColumnIndex + 1)
            {
                centre2.x -= HexMetrics.WrapSize * HexMetrics.InnerDiameter;
            }

            centre2.y = centre.y;
            var e2 = new EdgeVertices(
                centre2 + HexMetrics.GetSecondSolidCorner(direction.Opposite()),
                centre2 + HexMetrics.GetFirstSolidCorner(direction.Opposite())
                ); // rather than calculating from current centre, work backwards from neighbour centre to find edge

            if (cell.HasRiverThroughEdge(direction))
            {
                TriangulateEstuary(e1, e2, cell.IncomingRiver == direction, indices);
            }
            else
            {
                WaterShore.AddQuad(e1.v1, e1.v2, e2.v1, e2.v2);
                WaterShore.AddQuad(e1.v2, e1.v3, e2.v2, e2.v3);
                WaterShore.AddQuad(e1.v3, e1.v4, e2.v3, e2.v4);
                WaterShore.AddQuad(e1.v4, e1.v5, e2.v4, e2.v5);
                WaterShore.AddQuadUV(0f, 0f, 0f, 1f);
                WaterShore.AddQuadUV(0f, 0f, 0f, 1f);
                WaterShore.AddQuadUV(0f, 0f, 0f, 1f);
                WaterShore.AddQuadUV(0f, 0f, 0f, 1f);
                WaterShore.AddQuadCellData(indices, weights1, weights2);
                WaterShore.AddQuadCellData(indices, weights1, weights2);
                WaterShore.AddQuadCellData(indices, weights1, weights2);
                WaterShore.AddQuadCellData(indices, weights1, weights2);
            }

            var nextNeighbour = cell.GetNeighbour(direction.Next());

            if (nextNeighbour == null)
            {
                return;
            }

            var centre3 = nextNeighbour.Position;

            if (nextNeighbour.ColumnIndex < cell.ColumnIndex - 1)
            {
                centre3.x += HexMetrics.WrapSize * HexMetrics.InnerDiameter;
            }
            else if (nextNeighbour.ColumnIndex > cell.ColumnIndex + 1)
            {
                centre3.x -= HexMetrics.WrapSize * HexMetrics.InnerDiameter;
            }

            var v3 = centre3 +
                     (nextNeighbour.IsUnderwater ?
                      HexMetrics.GetFirstWaterCorner(direction.Previous()) :
                      HexMetrics.GetFirstSolidCorner(direction.Previous()));

            v3.y = centre.y;
            WaterShore.AddTriangle(e1.v5, e2.v5, v3);
            WaterShore.AddTriangleUV(
                new Vector2(0f, 0f),
                new Vector2(0f, 1f),
                new Vector2(0f, nextNeighbour.IsUnderwater ? 0f : 1f));
            indices.z = nextNeighbour.Index;
            WaterShore.AddTriangleCellData(indices, weights1, weights2, weights3);
        }
        private void TriangulateConnection(HexDirection direction, HexCell cell, EdgeVertices e1)
        {
            var neighbour = cell.GetNeighbour(direction);

            if (neighbour == null)
            {
                return; // dont add for edge hexes
            }
            var bridge = HexMetrics.GetBridge(direction);

            bridge.y = neighbour.Position.y - cell.Position.y;
            var e2 = new EdgeVertices(
                e1.v1 + bridge,
                e1.v5 + bridge
                );

            var hasRiver = cell.HasRiverThroughEdge(direction);
            var hasRoad  = cell.HasRoadThroughEdge(direction);

            if (hasRiver)
            {
                var startV3 = e2.v3.y;
                e2.v3.y = neighbour.StreamBedY;
                var indices = new Vector3(cell.Index, neighbour.Index, cell.Index);

                // by definition, both cells have rivers through them
                // however, if both are underwater, then we want (i want) no river bed
                // if only one is, the river should merge with the stream
                // EXCEPT if there is an elevation difference, in which case we need the stream bed to make a waterfall

                // if im a river and the neighbour is a river
                if (!cell.IsUnderwater && !neighbour.IsUnderwater)
                {
                    TriangulateRiverQuad(
                        e1.v2, e1.v4, e2.v2, e2.v4, cell.RiverSurfaceY, neighbour.RiverSurfaceY, 0.8f,
                        cell.HasIncomingRiver && cell.IncomingRiver == direction, indices);
                }
                // if im a river and the neighbour is beneath me
                else if (!cell.IsUnderwater && cell.Elevation > neighbour.WaterLevel)
                {
                    TriangulateWaterfallInWater(
                        e1.v2, e1.v4, e2.v2, e2.v4,
                        cell.RiverSurfaceY, neighbour.RiverSurfaceY,
                        neighbour.WaterLevel, indices);
                }
                // im underwater but the neighbour is heigher than me
                else if (cell.IsUnderwater && !neighbour.IsUnderwater && neighbour.Elevation > cell.WaterLevel)
                {
                    TriangulateWaterfallInWater(
                        e2.v4, e2.v2, e1.v4, e1.v2,
                        neighbour.RiverSurfaceY, cell.RiverSurfaceY,
                        cell.WaterLevel, indices);
                }
                else if ((cell.IsUnderwater == neighbour.IsUnderwater == true) || // both underwater
                         !cell.IsUnderwater && neighbour.IsUnderwater) // river into water on same level
                {
                    e2.v3.y = startV3;                                 // if a river, this will smooth e1 (river side) into e2 (lake/sea bed, which is normal surface)
                }
                // if not a river, then e1 is already sea/lake bed, so e2 will now be approximate same level
            }

            if (HexMetrics.GetEdgeType(cell.Elevation, neighbour.Elevation) == HexEdgeType.Slope)
            {
                TriangulateEdgeTerrace(e1, cell, e2, neighbour, hasRoad);
            }
            else
            {
                TriangulateEdgeStrip(e1, weights1, cell.Index, e2, weights2, neighbour.Index, hasRoad);
            }

            Features.AddWall(e1, cell, e2, neighbour, hasRiver, hasRoad);

            if (direction > HexDirection.E)
            {
                return;
            }
            var nextDirection = direction.Next();
            var nextNeighbour = cell.GetNeighbour(nextDirection);

            if (nextNeighbour == null)
            {
                return;
            }

            var v5 = e1.v5 + HexMetrics.GetBridge(nextDirection);

            v5.y = nextNeighbour.Position.y;

            var minElevation = Mathf.Min(cell.Elevation, neighbour.Elevation, nextNeighbour.Elevation);

            if (minElevation == cell.Elevation)
            {
                TriangulateCorner(e1.v5, cell, e2.v5, neighbour, v5, nextNeighbour);
            }
            else if (minElevation == neighbour.Elevation)
            {
                TriangulateCorner(e2.v5, neighbour, v5, nextNeighbour, e1.v5, cell);
            }
            else
            {
                TriangulateCorner(v5, nextNeighbour, e1.v5, cell, e2.v5, neighbour);
            }
        }