public EditorTile(int x, int y, int tileset, int srcX, int srcY, int terrain, EditorTileLayer layer)
        {
            X = x;
            Y = y;
            Tileset = tileset;
            SrcX = srcX;
            SrcY = srcY;
            Terrain = terrain;
            Layer = layer;

            HookEvents();
        }
 public LayerChangedEventArgs(EditorTileLayer oldLayer, EditorTileLayer newLayer)
 {
     _oldLayer = oldLayer;
     _newLayer = newLayer;
 }
 public LayerSelectedEventArgs(EditorTileLayer layer)
 {
     _layer = layer;
 }
        /// <summary>
        /// Clones the <see cref="EditorTileLayer"/> object.
        /// </summary>
        /// <returns>Copy of the object.</returns>
        public EditorTileLayer Clone()
        {
            var newLayer = new EditorTileLayer(Name, Opacity, Visible);
            newLayer.Tiles = new EditorTile[Tiles.GetLength(0), Tiles.GetLength(1)];

            for (int x = 0; x < Tiles.GetLength(0); x++)
            {
                for (int y = 0; y < Tiles.GetLength(1); y++)
                {
                    var tile = Tiles[x, y];
                    newLayer.Tiles[x, y] = new EditorTile(tile.X, tile.Y, tile.Tileset, tile.SrcX, tile.SrcY, tile.Terrain, newLayer);
                }
            }

            return newLayer;
        }
 public LayerAddedEventArgs(EditorTileLayer layer)
 {
     _layer = layer;
 }
        /// <summary>
        /// Creates a new layer.
        /// </summary>
        public void NewLayer()
        {
            using (var dialog = new DialogLayer())
            {
                var result = dialog.ShowDialog();
                if (result != DialogResult.OK) return;

                var name = dialog.LayerName;
                var opacity = dialog.LayerOpacity;
                var visible = dialog.LayerVisible;

                if (CheckLayer(name))
                {
                    MessageBox.Show(@"A layer with this name already exists.", @"New Layer");
                    return;
                }

                using (UndoRedoArea.Start("New Layer"))
                {
                    var layer = new EditorTileLayer(name, opacity, visible);

                    Layers.Add(layer);

                    if (LayerAdded != null)
                        LayerAdded.Invoke(this, new LayerAddedEventArgs(layer));

                    SelectLayer(layer.Name);

                    UnsavedChanges = true;

                    UndoRedoArea.Commit();
                }
            }
        }
        /// <summary>
        /// Removes a tile from the map.
        /// </summary>
        /// <param name="layer">Layer the tile is on.</param>
        /// <param name="destX">X co-ordinate of the tile.</param>
        /// <param name="destY">Y co-ordinate of the tile.</param>
        public void RemoveTile(EditorTileLayer layer, int destX, int destY)
        {
            if (destX < 0 || destY < 0 || destX > Width - 1 || destY > Height - 1) return;
            layer.Tiles[destX, destY].Tileset = 0;
            layer.Tiles[destX, destY].SrcX = 0;
            layer.Tiles[destX, destY].SrcY = 0;
            layer.Tiles[destX, destY].Terrain = 0;

            layer.Sprites[destX, destY] = null;
            layer.TerrainCache[destX, destY] = null;
        }
        /// <summary>
        /// Caches an individual tile's sprite.
        /// </summary>
        /// <param name="layer">Layer of the tile.</param>
        /// <param name="tile">Tile to cache.</param>
        private void CacheTile(EditorTileLayer layer, EditorTile tile)
        {
            layer.TerrainCache[tile.X, tile.Y] = null;

            var tileset = TilesetManager.Instance.GetTileset(tile.Tileset);
            if (tileset == null)
            {
                layer.Sprites[tile.X, tile.Y] = null;
                return;
            }

            layer.Sprites[tile.X, tile.Y] = new Sprite
            {
                Texture = ResourceManager.Instance.LoadTexture(tileset.Image),
                Position = new Vector2f(tile.X * tileset.TileWidth, tile.Y * tileset.TileHeight),
                TextureRect = new IntRect(tile.SrcX * tileset.TileWidth, tile.SrcY * tileset.TileHeight, tileset.TileWidth, tileset.TileHeight)
            };
        }
 /// <summary>
 /// Sets an individual tile to the map.
 /// </summary>
 /// <param name="tileset">Tileset of the tile.</param>
 /// <param name="layer">Layer to set the tile to.</param>
 /// <param name="destX">X co-ordinate to place to.</param>
 /// <param name="destY">Y co-ordinate to place to.</param>
 /// <param name="srcX">X co-ordinate of the tile on the tileset.</param>
 /// <param name="srcY">Y co-ordinate of the tile on the tileset.</param>
 private void SetTile(Tileset tileset, EditorTileLayer layer, int destX, int destY, int srcX, int srcY)
 {
     layer.Tiles[destX, destY].Tileset = tileset.ID;
     layer.Tiles[destX, destY].X = destX;
     layer.Tiles[destX, destY].Y = destY;
     layer.Tiles[destX, destY].SrcX = srcX;
     layer.Tiles[destX, destY].SrcY = srcY;
     layer.Tiles[destX, destY].Terrain = 0;
 }
        /// <summary>
        /// Caches an individual terrain tile's sprite.
        /// </summary>
        /// <param name="layer">Layer of the tile.</param>
        /// <param name="tile">Tile to cache.</param>
        private void CacheTerrainTile(EditorTileLayer layer, EditorTile tile)
        {
            layer.Sprites[tile.X, tile.Y] = null;

            var terrain = TerrainManager.Instance.GetTerrain(tile.Terrain);
            if (terrain == null)
            {
                layer.TerrainCache[tile.X, tile.Y] = null;
                return;
            }

            layer.TerrainCache[tile.X, tile.Y] = new TerrainCache();

            EditorTile NW; EditorTile N; EditorTile NE; EditorTile E; EditorTile SE; EditorTile S; EditorTile SW; EditorTile W;

            EditorTile forcedTile;
            if (!UndoRedoManager.IsCommandStarted && !UndoRedoArea.IsCommandStarted)
            {
                using (UndoRedoManager.Start("Creating fake tile"))
                {
                    forcedTile = new EditorTile(0, 0, 0, 0, 0, tile.Terrain);
                    UndoRedoManager.Commit();
                }
            }
            else
            {
                forcedTile = new EditorTile(0, 0, 0, 0, 0, tile.Terrain);
            }

            if (!(tile.X - 1 < 0 || tile.Y - 1 < 0))
                NW = layer.Tiles[tile.X - 1, tile.Y - 1];
            else
                NW = forcedTile;
            if (!(tile.Y - 1 < 0))
                N = layer.Tiles[tile.X, tile.Y - 1];
            else
                N = forcedTile;
            if (!(tile.X + 1 > Width - 1 || tile.Y - 1 < 0))
                NE = layer.Tiles[tile.X + 1, tile.Y - 1];
            else
                NE = forcedTile;
            if (!(tile.X + 1 > Width - 1))
                E = layer.Tiles[tile.X + 1, tile.Y];
            else
                E = forcedTile;
            if (!(tile.X + 1 > Width - 1 || tile.Y + 1 > Height - 1))
                SE = layer.Tiles[tile.X + 1, tile.Y + 1];
            else
                SE = forcedTile;
            if (!(tile.Y + 1 > Height - 1))
                S = layer.Tiles[tile.X, tile.Y + 1];
            else
                S = forcedTile;
            if (!(tile.X - 1 < 0 || tile.Y + 1 > Height - 1))
                SW = layer.Tiles[tile.X - 1, tile.Y + 1];
            else
                SW = forcedTile;
            if (!(tile.X - 1 < 0))
                W = layer.Tiles[tile.X - 1, tile.Y];
            else
                W = forcedTile;

            layer.TerrainCache[tile.X, tile.Y].Cache(tile.X, tile.Y, tile.Terrain, NW.Terrain, N.Terrain, NE.Terrain, E.Terrain, SE.Terrain, S.Terrain, SW.Terrain, W.Terrain);
        }
        private void CacheSurroundingTerrain(EditorTileLayer layer, EditorTile tile)
        {
            var tiles = new List<EditorTile>();

            if (!(tile.X - 1 < 0 || tile.Y - 1 < 0))
                tiles.Add(layer.Tiles[tile.X - 1, tile.Y - 1]);
            if (!(tile.Y - 1 < 0))
                tiles.Add(layer.Tiles[tile.X, tile.Y - 1]);
            if (!(tile.X + 1 > Width - 1 || tile.Y - 1 < 0))
                tiles.Add(layer.Tiles[tile.X + 1, tile.Y - 1]);
            if (!(tile.X + 1 > Width - 1))
                tiles.Add(layer.Tiles[tile.X + 1, tile.Y]);
            if (!(tile.X + 1 > Width - 1 || tile.Y + 1 > Height - 1))
                tiles.Add(layer.Tiles[tile.X + 1, tile.Y + 1]);
            if (!(tile.Y + 1 > Height - 1))
                tiles.Add(layer.Tiles[tile.X, tile.Y + 1]);
            if (!(tile.X - 1 < 0 || tile.Y + 1 > Height - 1))
                tiles.Add(layer.Tiles[tile.X - 1, tile.Y + 1]);
            if (!(tile.X - 1 < 0))
                tiles.Add(layer.Tiles[tile.X - 1, tile.Y]);

            foreach (var item in tiles)
            {
                if (item.Terrain > 0)
                    CacheTerrainTile(layer, item);
            }
        }
        /// <summary>
        /// Sets the selection of tiles to the map.
        /// </summary>
        /// <param name="tileset">Tileset of the tiles.</param>
        /// <param name="layer">Layer to set the tiles to.</param>
        /// <param name="selection">Selection of tiles to place.</param>
        /// <param name="x">X co-ordinate to place to.</param>
        /// <param name="y">Y co-orindate to place to.</param>
        public void SetTiles(Tileset tileset, EditorTileLayer layer, PointSelection selection, int x, int y)
        {
            foreach (var point in selection.Points)
            {
                var x2 = (x - selection.Offset.X) + point.X;
                var y2 = (y - selection.Offset.Y) + point.Y;

                if (x2 < 0 || y2 < 0 || x2 > Width - 1 || y2 > Height - 1) continue;

                SetTile(tileset, layer, x2, y2, point.X, point.Y);
            }
        }
        /// <summary>
        /// Sets a terrain tile
        /// </summary>
        /// <param name="layer">Layer to set the terrain to</param>
        /// <param name="terrain">TerrainTile to set down</param>
        /// <param name="destX">X co-ordinate to place to</param>
        /// <param name="destY">Y co-ordinate to place to</param>
        public void SetTerrain(EditorTileLayer layer, TerrainTile terrain, int destX, int destY)
        {
            if (destX < 0 || destY < 0 || destX > Width - 1 || destY > Height - 1) return;

            layer.Tiles[destX, destY].Tileset = 0;
            layer.Tiles[destX, destY].X = destX;
            layer.Tiles[destX, destY].Y = destY;
            layer.Tiles[destX, destY].SrcX = 0;
            layer.Tiles[destX, destY].SrcY = 0;
            layer.Tiles[destX, destY].Terrain = terrain.ID;
        }
        public void RevertToConcrete()
        {
            _building = true;
            _dontCache = true;

            Layers = new UndoRedoList<EditorTileLayer>();

            Width = ConcreteWidth;
            Height = ConcreteHeight;

            foreach (var layer in ConcreteLayers)
            {
                var newLayer = new EditorTileLayer(layer.Name, layer.Opacity, layer.Visible)
                {
                    Tiles = new EditorTile[Width,Height],
                    Sprites = new Sprite[Width,Height],
                    TerrainCache = new TerrainCache[Width,Height]
                };

                for (var x = 0; x < Width; x++)
                {
                    for (var y = 0; y < Height; y++)
                    {
                        newLayer.Tiles[x, y] = new EditorTile(x, y, 0, 0, 0, 0, newLayer);
                        newLayer.Tiles[x, y].PropertyChanged += Tile_PropertyChanged;
                    }
                }

                foreach (var tile in layer.Tiles)
                {
                    var newTile = newLayer.Tiles[tile.X, tile.Y];
                    newTile.X = tile.X;
                    newTile.Y = tile.Y;
                    newTile.Tileset = tile.Tileset;
                    newTile.SrcX = tile.SrcX;
                    newTile.SrcY = tile.SrcY;
                    newTile.Terrain = tile.Terrain;
                }

                Layers.Add(newLayer);
            }

            _building = false;
            _dontCache = false;

            CacheAllTiles();
        }