public void ApplyPath()
    {
        if (RoadMesh == null)
        {
            return;
        }
        Vector3Int    minV    = Vector3Int.RoundToInt(RoadMesh.GetComponent <MeshFilter>().mesh.bounds.min);
        Vector3Int    maxV    = Vector3Int.RoundToInt(RoadMesh.GetComponent <MeshFilter>().mesh.bounds.max);
        HashSet <int> indexes = new HashSet <int>();

        for (int x = minV.x; x <= maxV.x; x++)
        {
            for (int z = minV.z; z <= maxV.z; z++)
            {
                if (!Consts.IsWithinMapBounds(x, z))
                {
                    continue;
                }
                if (Physics.Raycast(new Vector3(x, Consts.MAX_H, z), Vector3.down, out RaycastHit hit, Consts.RAY_H, 1 << 14))
                {
                    int idx = Consts.PosToIndex(x, z);
                    indexes.Add(idx);
                    Vector3 for_buffer = Consts.IndexToPos(idx);
                    Consts.former_heights[idx]  = hit.point.y;
                    Consts.current_heights[idx] = Consts.former_heights[idx];
                    UndoBuffer.AddVertexPair(for_buffer, Consts.IndexToPos(idx));
                }
            }
        }
        Consts.UpdateMapColliders(indexes);
        //Search for any tiles
        var surr = Build.Get_surrounding_tiles(indexes);

        Build.UpdateTiles(surr);
        UndoBuffer.ApplyTerrainOperation();
        RemovePreview();
    }
    private void PasteSelectionOntoTerrain()
    {
        if (CopyClipboard.Count == 0)
        {
            return;
        }

        //Indexes of vertices for UpdateMapColliders()
        HashSet <int> indexes = new HashSet <int>();

        foreach (var mrk in CopyClipboard)
        {
            Vector3 pom = Highlight.pos + mrk;
            if (Consts.IsWithinMapBounds(pom))
            {
                // Update arrays of vertex heights
                int newindex = Consts.PosToIndex(pom);
                indexes.Add(newindex);
                Vector3 for_buffer = Consts.IndexToPos(newindex);
                if (pastingMode == PastingMode.fixed_height)
                {
                    Consts.current_heights[newindex] = fixed_height + mrk.y;
                    Consts.former_heights[newindex]  = fixed_height + mrk.y;
                }
                else if (pastingMode == PastingMode.addition)
                {
                    Consts.current_heights[newindex] = pom.y;
                    Consts.former_heights[newindex]  = pom.y;
                }
                UndoBuffer.AddVertexPair(for_buffer, Consts.IndexToPos(newindex));
            }
        }
        Consts.UpdateMapColliders(indexes);
        UndoBuffer.ApplyTerrainOperation();
        Build.UpdateTiles(Build.Get_surrounding_tiles(Markings, true));
    }
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Alpha1))
        {
            SwitchSubMode(0);
        }
        else if (Input.GetKeyDown(KeyCode.Alpha2))
        {
            SwitchSubMode(1);
            RemoveIndicator();
        }
        else if (Input.GetKeyDown(KeyCode.Alpha3))
        {
            SwitchSubMode(2);
            RemoveIndicator();
        }
        if (!Input.GetKey(KeyCode.LeftControl) && !MouseInputUIBlocker.BlockedByUI && Consts.IsWithinMapBounds(Highlight.pos))
        {
            if (submode == SubMode.Set)
            {
                if (Input.GetKey(KeyCode.LeftAlt) && Input.GetMouseButtonDown(0))
                {
                    FreeElevation();                     // single-action
                }
                else if (!Input.GetKey(KeyCode.LeftAlt) && Input.GetMouseButton(0))
                {
                    FreeElevation();                     //auto-fire
                }
                else if (Input.GetMouseButtonDown(1) && Highlight.over)
                {
                    RectangularElevation();
                }
            }
            else if (submode == SubMode.Avg)
            {
                if (Input.GetKey(KeyCode.LeftAlt) && Input.GetMouseButtonDown(0))
                {
                    Smoothing();                     // single-action
                }
                else if (!Input.GetKey(KeyCode.LeftAlt) && Input.GetMouseButton(0))
                {
                    Smoothing();                     //auto-fire
                }
                else if (Input.GetKey(KeyCode.LeftAlt) && Input.GetMouseButtonDown(1))
                {
                    Distortion();                     // single-action
                }
                else if (!Input.GetKey(KeyCode.LeftAlt) && Input.GetMouseButton(1))
                {
                    Distortion();                     //auto-fire
                }
            }
            else if (submode == SubMode.Amp)
            {
                if (Input.GetKey(KeyCode.LeftAlt) && Input.GetMouseButtonDown(0))
                {
                    Amplification();                     // single-action
                }
                else if (!Input.GetKey(KeyCode.LeftAlt) && Input.GetMouseButton(0))
                {
                    Amplification();                     //auto-fire
                }
                if (Input.GetKey(KeyCode.LeftAlt) && Input.GetMouseButtonDown(1))
                {
                    Amplification(-1);                     // single-action
                }
                else if (!Input.GetKey(KeyCode.LeftAlt) && Input.GetMouseButton(1))
                {
                    Amplification(-1);                     //auto-fire
                }
            }
        }
        if (Input.GetKeyDown(KeyCode.Tab))
        {
            RadiusSlider.GetComponent <Slider>().value = 1;
        }

        if (Input.GetMouseButtonUp(1) || Input.GetMouseButtonUp(0))
        {
            UndoBuffer.ApplyTerrainOperation();
            InitialPos = new Vector3(-1, -1, -1);
        }
        if (Input.GetKeyDown(KeyCode.Escape))         //ESC deletes white indicator in Make_Elevation()
        {
            RemoveIndicator();
        }
    }
    private void RectangularElevation()
    {
        if (P1.x == -1)
        {
            // Get initial position and set znacznik there
            P1        = Highlight.pos;
            P1_marker = GameObject.CreatePrimitive(PrimitiveType.Cube);
            P1_marker.transform.localScale = new Vector3(.25f, 1, .25f);
            P1_marker.transform.position   = Highlight.pos;
        }
        else
        {
            // Time to get second position
            Vector3       P2      = Highlight.pos;
            Vector3       BL      = new Vector3(Mathf.Min(P1.x, P2.x), 0, Mathf.Min(P1.z, P2.z));
            Vector3       TR      = new Vector3(Mathf.Max(P1.x, P2.x), 0, Mathf.Max(P1.z, P2.z));
            HashSet <int> indexes = new HashSet <int>();
            for (float z = BL.z - (int)RadiusSlider.value; z <= TR.z + RadiusSlider.value; z++)
            {
                for (float x = BL.x - (int)RadiusSlider.value; x <= TR.x + RadiusSlider.value; x++)
                {
                    if (Consts.IsWithinMapBounds(x, z))
                    {
                        int     idx        = Consts.PosToIndex((int)x, (int)z);
                        Vector3 currentpos = Consts.IndexToPos(idx);
                        if (x >= BL.x && x <= TR.x && z >= BL.z && z <= TR.z)
                        {
                            Consts.former_heights[idx] = Consts.SliderValue2RealHeight(HeightSlider.value);
                        }
                        else
                        {
                            Vector3 Closest = GetClosestEdgeVertex(currentpos, BL, TR);
                            float   dist    = Consts.Distance(currentpos, Closest);
                            if (Mathf.Round(dist) > RadiusSlider.value - 1)
                            {
                                continue;
                            }
                            float Hdiff = Consts.SliderValue2RealHeight(HeightSlider.value) - Consts.current_heights[idx];
                            Consts.former_heights[idx] += Hdiff * Consts.Smoothstep(0, 1, (RadiusSlider.value - dist) / RadiusSlider.value);
                        }
                        Consts.current_heights[idx] = Consts.former_heights[idx];
                        UndoBuffer.AddVertexPair(currentpos, Consts.IndexToPos(idx));
                        indexes.Add(idx);
                    }
                }
            }
            Consts.UpdateMapColliders(indexes);
            Vector3 center = new Vector3(0.5f * (P1.x + P2.x), Consts.MAX_H, 0.5f * (P1.z + P2.z));
            Vector3 bounds = new Vector3(0.5f * Mathf.Abs(P1.x - P2.x) + RadiusSlider.value + .5f, 1f,
                                         0.5f * Mathf.Abs(P1.z - P2.z) + RadiusSlider.value + .5f);
            RaycastHit[] hits = Physics.BoxCastAll(center, bounds, Vector3.down, Quaternion.identity, Consts.RAY_H, 1 << 9);
            Build.UpdateTiles(hits.Select(hit => hit.transform.gameObject).ToList());
            UndoBuffer.ApplyTerrainOperation();
            RemoveIndicator();
        }

        Vector3 GetClosestEdgeVertex(Vector3 v, Vector3 LD, Vector3 PG)
        {
            Vector3 result = new Vector3();

            if (v.x < LD.x)
            {
                result.x = LD.x;
            }
            else if (v.x > PG.x)
            {
                result.x = PG.x;
            }
            else
            {
                result.x = v.x;
            }

            if (v.z < LD.z)
            {
                result.z = LD.z;
            }
            else if (v.z > PG.z)
            {
                result.z = PG.z;
            }
            else
            {
                result.z = v.z;
            }
            return(result);
        }
    }