public void FillTiles(Point startPoint, NormalBrush brush)
    {
        var applyList = new HashSet<Texture2D>();

        var queue = new Queue<Point>();
        queue.Enqueue(startPoint);

        var targetTile = _tilerMap.GetTileFromWorldTile(startPoint, true);//.Properties.ID;
        if (targetTile == null) return;

        var targetProperty = targetTile.Properties;
        var replacementID = brush.GetBrush(startPoint.X, startPoint.Y);

        // Already match, just return
        if (replacementID.Properties.Equals(targetProperty))
            return;

        while (queue.Count > 0)
        {
            var p = queue.Dequeue();
            var tile = _tilerMap.GetTileFromWorldTile(p);

            if (tile != null && tile.Properties.Equals(targetProperty))
            {
                var changedTexture = ChangeTile(p, replacementID);
                applyList.Add(changedTexture);

                var left = new Point(p.X - 1, p.Y);
                queue.Enqueue(left);

                var right = new Point(p.X + 1, p.Y);
                queue.Enqueue(right);

                var bottom = new Point(p.X, p.Y - 1);
                queue.Enqueue(bottom);

                var top = new Point(p.X, p.Y + 1);
                queue.Enqueue(top);
            }
        }

        // Apply any changes
        foreach (var t in applyList)
        {
            t.Apply();
        }
    }
    private NormalBrush GetBrush(IEnumerable<Tileset> tilesets, Tile tile, int textureSize)
    {
        var c = tile.Collision;
        var collision = new bool[c.Length];
        Array.Copy(c, collision, c.Length);

        var id = tile.Properties.ID;
        var setID = (int) (id >> 32);

        Tileset ts = null;

        // Find matching tileset
// ReSharper disable LoopCanBeConvertedToQuery
        foreach (var t in tilesets)
// ReSharper restore LoopCanBeConvertedToQuery
        {
            if (t.TilesetID == setID)
            {
                ts = t;
                break;
            }
        }

        TileTexture tt = null;

        if (ts)
        {
            // Find matching tile
            tt = ts.Assets.Find(a => a.ID == id);
        }

        if (tt == null)
        {
            tt = TileTexture.None;
        }

        var brush = new NormalBrush(textureSize, tt);

        for (var i = 0; i < 4; i++)
        {
            if (brush.GetBrush().Properties.Rot == tile.Properties.Rot)
                break;

            brush.Rotate();
        }

        return brush;
    }
    public void ReplaceTiles(Point startPoint, NormalBrush brush)
    {
        var applyList = new HashSet<Texture2D>();

        var targetTile = _tilerMap.GetTileFromWorldTile(startPoint, true);//.Properties.ID;
        if (targetTile == null) return;

        var targetProperty = targetTile.Properties;
        var replacementID = brush.GetBrush(startPoint.X, startPoint.Y);

        // Already match, just return
        if (replacementID.Properties.Equals(targetProperty))
            return;

        foreach (var cell in _tilerMap.Cells)
        {
            for (int index = 0; index < cell.Tiles.Length; index++)
            {
                var tile = cell.Tiles[index];

                if (tile.Properties.Equals(targetProperty))
                {
                    var p = new Point
                                {
                                    X = index%_tilerMap.TilesPerCell, 
                                    Y = index/_tilerMap.TilesPerCell
                                };

                    var changedTexture = ChangeTile(cell, p, replacementID);
                    applyList.Add(changedTexture);
                }
            }
        }

        // Apply any changes
        foreach (var t in applyList)
        {
            t.Apply();
        }
    }