public void Fill(Tileset tileset, PointSelection selection, int x, int y) { if (x < 0 || x > Width - 1 || y < 0 || y > Height - 1) return; using (UndoRedoArea.Start("Fill Tool")) { _tileChecked = new bool[Width, Height]; _tileMap = SelectedLayer.Tiles; _tilesToCache = new List<Point>(); var tile = selection.GetTopLeftMostPoint(); var replacementTile = new FillTile(tileset.ID, tile.X, tile.Y, 0); var currTile = GetFillTile(x, y, replacementTile); var originalFillTile = new FillTile(currTile.Tileset, currTile.SrcX, currTile.SrcY, currTile.Terrain); FillTiles(currTile, originalFillTile, replacementTile); UndoRedoArea.Commit(); } }
/// <summary> /// Runs a flood-fill algorithm with the passed co-ordinates of the root. /// Returns an enumerable list of points based on the results. /// </summary> /// <param name="tileset">Tileset to replace with.</param> /// <param name="selection">Tile selection to replace with.</param> /// <param name="x">X co-ordinate of the root tile.</param> /// <param name="y">Y co-ordinate of the root tile.</param> /// <returns>An enumerable list of points.</returns> public List<Point> FillCache(Tileset tileset, PointSelection selection, int x, int y) { if (x < 0 || x > Width - 1 || y < 0 || y > Height - 1) return null; _tileCache = new List<Point>(); _cacheMap = new FillTile[Width, Height]; for (var x2 = 0; x2 < Width; x2++) { for (var y2 = 0; y2 < Height; y2++) { var tile = SelectedLayer.Tiles[x2, y2]; _cacheMap[x2, y2] = new FillTile(tile.Tileset, tile.SrcX, tile.SrcY, tile.Terrain); } } _tileChecked = new bool[Width, Height]; var point = selection.GetTopLeftMostPoint(); var replacementTile = new FillTile(tileset.ID, point.X, point.Y, 0); var currTile = GetFillCacheTile(x, y, replacementTile); var originalFillTile = new FillTile(currTile.Tileset, currTile.X, currTile.Y, currTile.Terrain); FillCacheTiles(originalFillTile, replacementTile, x, y); return _tileCache; }
/// <summary> /// Compares two FillTile objects. /// </summary> /// <param name="targetTile">Object to compare against.</param> /// <param name="replacementTile">Object to compare to.</param> /// <returns>True if tiles match, false if not.</returns> public bool CompareCacheTile(FillTile targetTile, FillTile replacementTile) { return targetTile.Tileset == replacementTile.Tileset && targetTile.X == replacementTile.X && targetTile.Y == replacementTile.Y && targetTile.Terrain == replacementTile.Terrain; }
public bool CompareTile(EditorTile targetTile, FillTile replacementTile) { return targetTile.Tileset == replacementTile.Tileset && targetTile.SrcX == replacementTile.X && targetTile.SrcY == replacementTile.Y && targetTile.Terrain == replacementTile.Terrain; }
private EditorTile GetFillTile(int x, int y, FillTile fillTile) { var tile = _tileMap[x, y] ?? new EditorTile(fillTile.Tileset, x, y, fillTile.X, fillTile.Y, 0); return tile; }
/// <summary> /// If a cache map tile doesn't exist, it'll create a new fill tile. /// </summary> /// <param name="x">X co-ordinate of the tile.</param> /// <param name="y">Y co-ordinate of the tile.</param> /// <param name="fillTile">Tile to replace with.</param> /// <returns>Returns a generated FillTile object.</returns> private FillTile GetFillCacheTile(int x, int y, FillTile fillTile) { var tile = _cacheMap[x, y] ?? new FillTile(fillTile.Tileset, x, y, 0); return tile; }
private void FillTiles(EditorTile tile, FillTile originalTile, FillTile replacementTile) { var open = new Queue<Point>(); open.Enqueue(new Point(tile.X, tile.Y)); while (open.Count > 0) { var current = open.Dequeue(); var x = current.X; var y = current.Y; CheckFillTile(open, x, y, originalTile, replacementTile); if (x > 0) CheckFillTile(open, x - 1, y, originalTile, replacementTile); if (x < Width - 1) CheckFillTile(open, x + 1, y, originalTile, replacementTile); if (y > 0) CheckFillTile(open, x, y - 1, originalTile, replacementTile); if (y < Height - 1) CheckFillTile(open, x, y + 1, originalTile, replacementTile); } SelectedLayer.Tiles = _tileMap; foreach (var tmp in SelectedLayer.Tiles) { tmp.PropertyChanged += Tile_PropertyChanged; } foreach (var point in _tilesToCache) { CacheTile(SelectedLayer, SelectedLayer.Tiles[point.X, point.Y]); } }
/// <summary> /// Begins the actual flood-fill algorithm. Should only be called from the <see cref="FillCache"/> method. /// </summary> /// <param name="originalTile">Root tile to check.</param> /// <param name="replacementTile">Tile to replace all tiles with.</param> /// <param name="destx">Root X co-ordinate.</param> /// <param name="desty">Root Y co-ordinate.</param> private void FillCacheTiles(FillTile originalTile, FillTile replacementTile, int destx, int desty) { var open = new Queue<Point>(); open.Enqueue(new Point(destx, desty)); while (open.Count > 0) { var current = open.Dequeue(); var x = current.X; var y = current.Y; CheckCacheFillTile(open, x, y, originalTile, replacementTile); if (x > 0) CheckCacheFillTile(open, x - 1, y, originalTile, replacementTile); if (x < Width - 1) CheckCacheFillTile(open, x + 1, y, originalTile, replacementTile); if (y > 0) CheckCacheFillTile(open, x, y - 1, originalTile, replacementTile); if (y < Height - 1) CheckCacheFillTile(open, x, y + 1, originalTile, replacementTile); } }
private void CheckFillTile(Queue<Point> open, int x, int y, FillTile originalTile, FillTile replacementTile) { if (_tileChecked[x, y]) return; var currTile = GetFillTile(x, y, replacementTile); if (CompareTile(currTile, originalTile)) { currTile.Tileset = replacementTile.Tileset; currTile.SrcX = replacementTile.X; currTile.SrcY = replacementTile.Y; currTile.X = x; currTile.Y = y; currTile.Terrain = replacementTile.Terrain; _tilesToCache.Add(new Point(x, y)); _tileChecked[x, y] = true; open.Enqueue(new Point(x, y)); } }