예제 #1
0
    void FillHole(SquareCell cell, Vector3 v1)
    {
        SquareCell eastNeighbor      = cell.GetNeighbor(SquareDirection.E);
        SquareCell northNeighbor     = cell.GetNeighbor(SquareDirection.N);
        SquareCell northEastNeighbor = null;

        if (northNeighbor == null || eastNeighbor == null)
        {
            return;
        }

        northEastNeighbor = cell.GetNeighbor(SquareDirection.N).GetNeighbor(SquareDirection.E);

        Vector3 bridgeN = SquareMetrics.GetBridge(SquareDirection.N);
        Vector3 n       = v1 + bridgeN;

        Vector3 bridgeE = SquareMetrics.GetBridge(SquareDirection.E);
        Vector3 e       = v1 + bridgeE;

        Vector3 ne = v1 + bridgeN + bridgeE;

        Color northColor, eastColor, northEastColor;

        northColor = eastColor = northEastColor = cell.Color;

        if (northNeighbor != null)
        {
            n.y        = northNeighbor.transform.localPosition.y;
            northColor = northNeighbor.Color;
        }
        if (eastNeighbor != null)
        {
            e.y       = eastNeighbor.transform.localPosition.y;
            eastColor = eastNeighbor.Color;
        }
        if (northEastNeighbor != null)
        {
            ne.y           = northEastNeighbor.transform.localPosition.y;
            northEastColor = northEastNeighbor.Color;
        }

        Vector3 center = v1 + 0.5f * (bridgeN + bridgeE);

        center.y = (Mathf.Max(v1.y, e.y, n.y, ne.y) + Mathf.Min(v1.y, e.y, n.y, ne.y)) / 2f;
        Color blendColor = GetBlendColor(cell.Color, northColor, eastColor, northEastColor);

        // Triangle vertices should be clockwise
        // First Triangle to add will be v1, n, center
        AddTriangle(v1, n, center);
        AddTriangleColor(cell.Color, northColor, blendColor);
        // Second will be v1, center, e
        AddTriangle(v1, center, e);
        AddTriangleColor(cell.Color, blendColor, eastColor);
        // Third will be n, ne, center
        AddTriangle(n, ne, center);
        AddTriangleColor(northColor, northEastColor, blendColor);
        // Last is ne, e, center
        AddTriangle(ne, e, center);
        AddTriangleColor(northEastColor, eastColor, blendColor);
    }
예제 #2
0
 public void ConnectWithNeighbours()
 {
     for (int i = 0; i < 8; i += 2)
     {
         if (parentCell.HasRoadThroughEdge((GridDirection)i) && parentCell.GetNeighbor((GridDirection)i).roadNetwork.nodes.Count > 0)
         {
             ConnectWithNeigbour(parentCell.GetNeighbor((GridDirection)i), (GridDirection)i);
         }
     }
 }
예제 #3
0
    public void AddRoad()
    {
        SquareCell    randomRoad      = townRoads[Random.Range(0, townRoads.Count)];
        GridDirection randomDirection = (GridDirection)(Random.Range(0, 3) * 2);
        SquareCell    randomNeighbour = randomRoad.GetNeighbor(randomDirection);

        if (randomNeighbour && randomNeighbour.UrbanLevel == 0 && !townRoads.Contains(randomNeighbour))
        {
            randomRoad.AddRoad(randomDirection);
            randomNeighbour.AddRoad(randomDirection.Opposite());
            townRoads.Add(randomNeighbour);
        }
    }
예제 #4
0
    public void MakeBuilding()
    {
        SquareCell    randomRoad      = townRoads[Random.Range(0, townRoads.Count)];
        GridDirection randomDirection = (GridDirection)(Random.Range(0, 3) * 2);
        SquareCell    randomNeighbour = randomRoad.GetNeighbor(randomDirection);

        if (randomNeighbour && !randomNeighbour.HasRoads)
        {
            randomNeighbour.UrbanLevel++;
            if (!townBuildings.Contains(randomNeighbour))
            {
                townBuildings.Add(randomNeighbour);
            }
        }
    }
예제 #5
0
    private void BuildBridge(SquareDirection direction, SquareCell cell, Vector3 v1, Vector3 v2)
    {
        SquareCell neighbor = cell.GetNeighbor(direction);

        if (neighbor == null)
        {
            return;
        }
        Vector3 bridge = SquareMetrics.GetBridge(direction);
        Vector3 v3     = v1 + bridge;
        Vector3 v4     = v2 + bridge;

        v3.y = v4.y = neighbor.transform.localPosition.y;

        AddQuad(v1, v2, v3, v4);
        AddQuadColor(cell.Color, neighbor.Color);
    }
예제 #6
0
    void AddCliffEdge(SquareCell cell, GridDirection direction)
    {
        GridDirection prev     = direction.Previous();
        GridDirection next     = direction.Next();
        GridDirection prevN    = prev.Previous2();
        GridDirection nextN    = next.Next2();
        SquareCell    neighbor = cell.GetNeighbor(direction);

        if (neighbor != null)
        {
            Vector3 c0 = new Vector3(cell.coordinates.X, 0, cell.coordinates.Z) + GridMetrics.GetEdge(prev) + Vector3.up * (int)cell.GridElevations[prev] * GridMetrics.elevationStep;
            Vector3 c1 = new Vector3(cell.coordinates.X, 0, cell.coordinates.Z) + GridMetrics.GetEdge(next) + Vector3.up * (int)cell.GridElevations[next] * GridMetrics.elevationStep;
            Vector3 n0 = new Vector3(neighbor.coordinates.X, 0, neighbor.coordinates.Z) + GridMetrics.GetEdge(prevN) + Vector3.up * (int)neighbor.GridElevations[prevN] * GridMetrics.elevationStep;
            Vector3 n1 = new Vector3(neighbor.coordinates.X, 0, neighbor.coordinates.Z) + GridMetrics.GetEdge(nextN) + Vector3.up * (int)neighbor.GridElevations[nextN] * GridMetrics.elevationStep;
            if (c0 != n0 && c1 != n1)
            {
                if (c0.y > n0.y && n1.y > c1.y) // if edges cross heights along edge X
                {
                    Vector2 cross      = CrossingPoint(c1.y - c0.y, n1.y - n0.y, c0.y, n0.y);
                    Vector3 worldCross = new Vector3(cell.coordinates.X, 0, cell.coordinates.Z)
                                         + GridMetrics.GetEdge(direction.Previous())
                                         + (cross.x * 2 * GridMetrics.GetEdge(direction.Next2()))
                                         + new Vector3(0, cross.y, 0);
                    terrain.AddTriangle(worldCross, c0, n0);
                    terrain.AddTriangleColor(Color.cyan);
                    terrain.AddTriangle(worldCross, n1, c1);
                    terrain.AddTriangleColor(Color.green);
                }
                else if (c0.y > n0.y && c1.y > n1.y) // if one edge is always above the other
                {
                    terrain.AddQuad(c0, n0, n1, c1);
                    terrain.AddQuadColor(retainingWallColor);
                }
            }
            else if (c0.y > n0.y)
            {
                terrain.AddTriangle(c0, n0, c1);
                terrain.AddTriangleColor(retainingWallColor);
            }
            else if (c1.y > n1.y)
            {
                terrain.AddTriangle(c0, n1, c1);
                terrain.AddTriangleColor(retainingWallColor);
            }
        }
    }
예제 #7
0
    public void SetupFoundations(SquareCell origin)
    {
        List <SquareCell> foundationList = new List <SquareCell>();

        height = origin.GetMaxElevation();
        owner  = origin.Town;
        SquareCell tempCellx = origin;
        SquareCell tempCelly = origin;

        for (int x = 0; x < width; x++)
        {
            tempCelly = tempCellx;
            for (int y = 0; y < depth; y++)
            {
                foundationList.Add(tempCelly);
                tempCelly = tempCelly.GetNeighbor(GridDirection.N);
            }
            tempCellx = tempCellx.GetNeighbor(GridDirection.E);
        }
        Foundations = foundationList.ToArray();
    }
예제 #8
0
    void TriangulateWithRiver(
        GridDirection direction, SquareCell cell, Vector3 centre, Vector3 v0, Vector3 v1, Vector3 v2, Vector3 v3, float v
        )
    {
        GridDirection flowDirection;
        bool          reversed = cell.HasIncomingRiver[(int)direction];

        if (cell.HasOutgoingRiver[(int)direction])
        {
            flowDirection = direction;
        }
        else if (reversed)
        {
            flowDirection = direction.Opposite();
        }
        else
        {
            if (cell.HasIncomingRiver[(int)direction.Next2()] && cell.HasOutgoingRiver[(int)direction.Previous2()])
            {
                flowDirection = direction.Previous2();
            }
            else if (cell.HasOutgoingRiver[(int)direction.Next2()] && cell.HasIncomingRiver[(int)direction.Previous2()])
            {
                flowDirection = direction.Next2();
            }
            else
            {
                flowDirection = direction.Opposite();
            }
        }
        TriangulateRiverTri(centre, v0, v3, cell.RiverSurfaceY, reversed, direction, flowDirection);
        SquareCell neighbor = cell.GetNeighbor(direction);

        if (neighbor && cell.HasRiverThroughEdge(direction))
        {
            TriangulateRiverQuad(v3, v0, v1, v2, cell.RiverSurfaceY, neighbor.RiverSurfaceY, 0.8f, reversed);
        }
    }
예제 #9
0
 void EditCell(SquareCell cell, Vector3 hitpoint)
 {
     if (activeMode == EditMode.color)
     {
         cell.Tile = activeTileMaterial.GetClone;
     }
     else if (activeMode == EditMode.elevation)
     {
         GridDirection vertex = squareGrid.GetVertex(hitpoint);
         if (Input.GetMouseButton(0) && (stopWatch.ElapsedMilliseconds > 500f || freshClick))
         {
             cell.ChangeVertexElevation(vertex, 1);
             if (!allowCliffs)
             {
                 if (cell.GetNeighbor(vertex))
                 {
                     cell.GetNeighbor(vertex).ChangeVertexElevation(vertex.Opposite(), 1);
                 }
                 if (cell.GetNeighbor(vertex.Next()))
                 {
                     cell.GetNeighbor(vertex.Next()).ChangeVertexElevation(vertex.Previous2(), 1);
                 }
                 if (cell.GetNeighbor(vertex.Previous()))
                 {
                     cell.GetNeighbor(vertex.Previous()).ChangeVertexElevation(vertex.Next2(), 1);
                 }
             }
             stopWatch.Reset();
             stopWatch.Start();
         }
         if (Input.GetMouseButton(1) && (stopWatch.ElapsedMilliseconds > 500f || freshClick))
         {
             cell.ChangeVertexElevation(vertex, -1);
             if (!allowCliffs)
             {
                 if (cell.GetNeighbor(vertex))
                 {
                     cell.GetNeighbor(vertex).ChangeVertexElevation(vertex.Opposite(), -1);
                 }
                 if (cell.GetNeighbor(vertex.Next()))
                 {
                     cell.GetNeighbor(vertex.Next()).ChangeVertexElevation(vertex.Previous2(), -1);
                 }
                 if (cell.GetNeighbor(vertex.Previous()))
                 {
                     cell.GetNeighbor(vertex.Previous()).ChangeVertexElevation(vertex.Next2(), -1);
                 }
             }
             stopWatch.Reset();
             stopWatch.Start();
         }
     }
     else if (activeMode == EditMode.rivers)
     {
         if (Input.GetMouseButton(1))
         {
             cell.RemoveRivers();
             Explosion(cell);
         }
         else if (isDrag)
         {
             SquareCell otherCell = cell.GetNeighbor(dragDirection.Opposite()); // work with brushes
             if (otherCell)
             {
                 otherCell.SetOutgoingRiver(dragDirection);
             }
         }
     }
     else if (activeMode == EditMode.roads)
     {
         float fracX = hitpoint.x - Mathf.Floor(hitpoint.x);
         float fracZ = hitpoint.z - Mathf.Floor(hitpoint.z);
         if (fracX > 0.25f && fracX < 0.75f || fracZ > 0.25f && fracZ < 0.75f)
         {
             GridDirection edge = squareGrid.GetEdge(hitpoint);
             if (Input.GetMouseButton(1))
             {
                 cell.RemoveRoad(edge);
                 Explosion(cell);
             }
             else
             {
                 cell.AddRoad(edge);
             }
         }
     }
     else if (activeMode == EditMode.water_level)
     {
         if (Input.GetMouseButton(0) && freshClick)
         {
             cell.WaterLevel++;
         }
         else if (Input.GetMouseButton(1) && freshClick)
         {
             cell.WaterLevel--;
         }
     }
     else if (activeMode == EditMode.building)
     {
         if (Input.GetMouseButton(0) && freshClick)
         {
             cell.UrbanLevel++;
         }
         if (Input.GetMouseButton(1) && freshClick)
         {
             cell.UrbanLevel = 0;
             Explosion(cell);
         }
     }
     else if (activeMode == EditMode.trees)
     {
         if (Input.GetMouseButton(0) && freshClick)
         {
             cell.PlantLevel++;
         }
         if (Input.GetMouseButton(1) && freshClick)
         {
             cell.PlantLevel = 0;
             Explosion(cell);
         }
     }
     else if (activeMode == EditMode.rocks)
     {
         if (Input.GetMouseButton(0) && freshClick)
         {
             cell.ScenaryObject = 1;
         }
         if (Input.GetMouseButton(1) && freshClick)
         {
             cell.ScenaryObject = 0;
             Explosion(cell);
         }
     }
     else if (activeMode == EditMode.mast)
     {
         if (Input.GetMouseButton(0) && freshClick)
         {
             cell.ScenaryObject = 2;
         }
         if (Input.GetMouseButton(1) && freshClick)
         {
             cell.ScenaryObject = 0;
             Explosion(cell);
         }
     }
     else if (activeMode == EditMode.lighthouse)
     {
         if (Input.GetMouseButton(0) && freshClick)
         {
             cell.ScenaryObject = 3;
         }
         if (Input.GetMouseButton(1) && freshClick)
         {
             cell.ScenaryObject = 0;
             Explosion(cell);
         }
     }
     else if (activeMode == EditMode.industry)
     {
         if (Input.GetMouseButton(0) && freshClick)
         {
             cell.Industry = (int)activeIndustry + 1;
         }
         if (Input.GetMouseButton(1) && freshClick)
         {
             cell.Industry = 0;
             Explosion(cell);
         }
     }
     else if (activeMode == EditMode.town)
     {
         if (cell.Town == null)
         {
             GameObject  town    = Instantiate(townPrefab);
             TownManager manager = town.GetComponent <TownManager>();
             town.transform.position = GridCoordinates.ToPosition(cell.coordinates) + new Vector3(0, cell.CentreElevation * GridMetrics.elevationStep, 0);
             manager.Init(cell);
             cell.Town = manager;
         }
     }
 }
예제 #10
0
    void AddColors(SquareCell cell, GridDirection direction)
    {
        SquareCell prevNeighbor  = cell.GetNeighbor(direction.Previous()) ?? cell;
        SquareCell neighbor      = cell.GetNeighbor(direction) ?? cell;
        SquareCell nextNeighbor  = cell.GetNeighbor(direction.Next()) ?? cell;
        SquareCell next2Neighbor = cell.GetNeighbor(direction.Next2()) ?? cell;
        SquareCell next3Neighbor = cell.GetNeighbor(direction.Next3()) ?? cell;

        Color previousMix     = (GetColor(prevNeighbor, cell) + cell.Color) / 2f;
        Color neighborMix     = (GetColor(neighbor, cell) + cell.Color + GetColor(prevNeighbor, cell) + GetColor(nextNeighbor, cell)) / 4f;
        Color nextMix         = (GetColor(nextNeighbor, cell) + cell.Color) / 2f;
        Color nextNeighborMix = (GetColor(nextNeighbor, cell) + cell.Color + GetColor(next2Neighbor, cell) + GetColor(next3Neighbor, cell)) / 4f;
        Color next2Mix        = (GetColor(next3Neighbor, cell) + cell.Color) / 2f;

        if (cell.HasRiver)
        {
            if (cell.HasRiverThroughEdge(direction.Previous()))
            {
                terrain.AddTriangleColor(cell.Color);
            }
            if (cell.HasRiverThroughEdge(direction.Next()))
            {
                terrain.AddTriangleColor(cell.Color);
            }
            terrain.AddTriangleColor(cell.Color);
            terrain.AddTriangleColor(cell.Color);
        }
        else
        {
            terrain.AddTriangleColor(cell.Color);
        }
        if (cell.HasRiverThroughEdge(direction.Next()))
        {
            terrain.AddQuadColor(cell.Color, nextMix, nextMix, cell.Color);
            terrain.AddQuadColor(cell.Color, nextMix, nextMix, cell.Color);
        }
        else
        {
            terrain.AddQuadColor(cell.Color, nextMix, nextMix, cell.Color);
        }                                                                   // next Edge
        if (cell.HasRiverThroughEdge(direction.Previous()))
        {
            terrain.AddQuadColor(cell.Color, cell.Color, previousMix, previousMix);
            terrain.AddQuadColor(cell.Color, cell.Color, previousMix, previousMix);
        }
        else
        {
            terrain.AddQuadColor(cell.Color, cell.Color, previousMix, previousMix);
        }                                                                            // previous Edge
        if (cell.HasRiverThroughEdge(direction))
        {
        }
        else
        {
            terrain.AddQuadColor(cell.Color, previousMix, neighborMix, nextMix);
        }                                                                        // direction Corner
        if (cell.HasRiverThroughEdge(direction.Next2()))
        {
        }
        else
        {
            terrain.AddQuadColor(cell.Color, nextMix, nextNeighborMix, next2Mix);
        }                                                                        // next Corner
    }
예제 #11
0
    void AddHalfCell(SquareCell cell, GridDirection direction, Vector3 centre, Vector3 v0, Vector3 v1, Vector3 v2, Vector3 va, Vector3 vb, Vector3 vc, Vector3 vd, Vector3 vx, Vector3 vy, Vector3 vz)
    {
        Vector3    riverbed         = centre + Vector3.up * (cell.CentreElevation + GridMetrics.streamBedElevationOffset) * GridMetrics.elevationStep;
        Vector3    midSolidEdgePrev = centre + GridMetrics.GetSolidEdge(direction.Previous()) + Vector3.up * (cell.CentreElevation + GridMetrics.streamBedElevationOffset) * GridMetrics.elevationStep;
        Vector3    midSolidEdgeNext = centre + GridMetrics.GetSolidEdge(direction.Next()) + Vector3.up * (cell.CentreElevation + GridMetrics.streamBedElevationOffset) * GridMetrics.elevationStep;
        SquareCell neighborPrev     = cell.GetNeighbor(direction.Previous()) ?? cell;
        SquareCell neighborNext     = cell.GetNeighbor(direction.Next()) ?? cell;
        Vector3    midEdgePrev      = centre + GridMetrics.GetEdge(direction.Previous()) + Vector3.up * ((cell.CentreElevation + neighborPrev.CentreElevation) / 2 + GridMetrics.streamBedElevationOffset) * GridMetrics.elevationStep;
        Vector3    midEdgeNext      = centre + GridMetrics.GetEdge(direction.Next()) + Vector3.up * ((cell.CentreElevation + neighborNext.CentreElevation) / 2 + GridMetrics.streamBedElevationOffset) * GridMetrics.elevationStep;

        if (cell.HasRiver)
        {
            if (cell.HasRiverThroughEdge(direction.Previous()))
            {
                terrain.AddTriangle(v0, midSolidEdgePrev, riverbed); // split tri into two tris
                terrain.AddTriangle(midSolidEdgePrev, v1, riverbed);
            }
            else
            {
                terrain.AddTriangle(v0, v1, riverbed);
            }                                          // edge with no river
            if (cell.HasRiverThroughEdge(direction.Next()))
            {
                terrain.AddTriangle(v1, midSolidEdgeNext, riverbed); // split tri into two tris
                terrain.AddTriangle(midSolidEdgeNext, v2, riverbed);
            }
            else
            {
                terrain.AddTriangle(v1, v2, riverbed);
            }                                          // edge with no river
        }
        else
        {
            terrain.AddTriangle(v0, v1, v2);
        }

        if (cell.HasRiverThroughEdge(direction.Next()))
        {
            terrain.AddQuad(v1, va, midEdgeNext, midSolidEdgeNext);
            terrain.AddQuad(midSolidEdgeNext, midEdgeNext, vb, v2);
        }
        else
        {
            terrain.AddQuad(v1, va, vb, v2);
        }                                    // top Edge
        if (cell.HasRiverThroughEdge(direction.Previous()))
        {
            terrain.AddQuad(v1, midSolidEdgePrev, midEdgePrev, vd);
            terrain.AddQuad(midSolidEdgePrev, v0, vc, midEdgePrev);
        }
        else
        {
            terrain.AddQuad(v1, v0, vc, vd);
        }                                     // left Edge
        if (cell.HasRiverThroughEdge(direction))
        {
        }
        else
        {
            terrain.AddQuad(v1, vd, vx, va);
        }                                    // direction edge
        if (cell.HasRiverThroughEdge(direction.Next2()))
        {
        }
        else
        {
            terrain.AddQuad(v2, vb, vy, vz);
        }                                   // clockwise edge
        AddColors(cell, direction);

        if (cell.HasRoadThroughEdge(direction.Next()))
        {
            midEdgeNext      = centre + GridMetrics.GetEdge(direction.Next()) + Vector3.up * ((int)cell.GridElevations[direction] + (int)cell.GridElevations[direction.Next2()]) / 2 * GridMetrics.elevationStep;
            midSolidEdgeNext = centre + GridMetrics.GetSolidEdge(direction.Next()) + Vector3.up * ((int)cell.GridElevations[direction] + (int)cell.GridElevations[direction.Next2()]) / 2 * GridMetrics.elevationStep;
            TriangulateRoadSegment(v1, midSolidEdgeNext, v2, va, midEdgeNext, vb);
        }
        if (cell.HasRoadThroughEdge(direction.Previous()))
        {
            midEdgePrev      = centre + GridMetrics.GetEdge(direction.Previous()) + Vector3.up * ((int)cell.GridElevations[direction] + (int)cell.GridElevations[direction.Previous2()]) / 2 * GridMetrics.elevationStep;
            midSolidEdgePrev = centre + GridMetrics.GetSolidEdge(direction.Previous()) + Vector3.up * ((int)cell.GridElevations[direction] + (int)cell.GridElevations[direction.Previous2()]) / 2 * GridMetrics.elevationStep;
            TriangulateRoadSegment(v0, midSolidEdgePrev, v1, vc, midEdgePrev, vd);
        }
    }
예제 #12
0
    void AddWaterForSquare(SquareCell cell, Vector3 centre)
    {
        centre.y = cell.WaterSurfaceY;
        Vector3 c0 = centre + GridMetrics.GetEdge(GridDirection.SW);
        Vector3 c1 = centre + GridMetrics.GetEdge(GridDirection.NW);
        Vector3 c2 = centre + GridMetrics.GetEdge(GridDirection.NE);
        Vector3 c3 = centre + GridMetrics.GetEdge(GridDirection.SE);

        if (cell.IsFullyUnderwater)
        {
            water.AddQuad(c0, c1, c2, c3);
        }
        else if (cell.IsPartUnderwater)
        {
            float v0 = 0f, v1 = 0f, v2 = 0f, v3 = 0f;
            if (cell.GetNeighbor(GridDirection.N) && !cell.GetNeighbor(GridDirection.N).IsUnderwater)
            {
                v1 = 1f; v2 = 1f;
            }
            if (cell.GetNeighbor(GridDirection.NE) && !cell.GetNeighbor(GridDirection.NE).IsUnderwater)
            {
                v2 = 1f;
            }
            if (cell.GetNeighbor(GridDirection.E) && !cell.GetNeighbor(GridDirection.E).IsUnderwater)
            {
                v2 = 1f; v3 = 1f;
            }
            if (cell.GetNeighbor(GridDirection.SE) && !cell.GetNeighbor(GridDirection.SE).IsUnderwater)
            {
                v3 = 1f;
            }
            if (cell.GetNeighbor(GridDirection.S) && !cell.GetNeighbor(GridDirection.S).IsUnderwater)
            {
                v3 = 1f; v0 = 1f;
            }
            if (cell.GetNeighbor(GridDirection.SW) && !cell.GetNeighbor(GridDirection.SW).IsUnderwater)
            {
                v0 = 1f;
            }
            if (cell.GetNeighbor(GridDirection.W) && !cell.GetNeighbor(GridDirection.W).IsUnderwater)
            {
                v0 = 1f; v1 = 1f;
            }
            if (cell.GetNeighbor(GridDirection.NW) && !cell.GetNeighbor(GridDirection.NW).IsUnderwater)
            {
                v1 = 1f;
            }
            waterShore.AddQuad(c0, c1, c2, c3);
            waterShore.AddQuadV(v0, v1, v2, v3);
        }
    }