static TiledMapTileset ParseTileset(XmlNode tilesetXml) { var tileset = new TiledMapTileset(); tileset.FirstGID = int.Parse(tilesetXml.Attributes["firstgid"].Value); var tilesetDir = ""; if (tilesetXml.Attributes["source"] != null) { ExternalTilesetsFirstGID.Add( Path.GetFullPath(TiledMapImporter.CurrentRootDir + '/' + tilesetXml.Attributes["source"].Value), (uint)tileset.FirstGID ); // If there is "source" field, that means, tileset is external. var doc = new XmlDocument(); try { // Paths in tileset file are relative to that file, so root dir needs to be swapped. TiledMapImporter.CurrentRootDir = TiledMapImporter.TmxRootDir + Path.GetDirectoryName(tilesetXml.Attributes["source"].Value) + "/"; doc.Load(TiledMapImporter.CurrentRootDir + "/" + Path.GetFileName(tilesetXml.Attributes["source"].Value)); tilesetDir = Path.GetDirectoryName(tilesetXml.Attributes["source"].Value) + '/'; tilesetXml = doc["tileset"]; // Swapping to actual tileset. } catch (Exception e) { throw new Exception("Error loading external tileset! " + e.Message + " " + e.StackTrace); } } tileset.Properties = XmlHelper.GetProperties(tilesetXml); // This means, that tileset won't be used in the game and should be ignored. if ( tileset.Properties.ContainsKey(IgnoreTilesetFlag) && bool.Parse(tileset.Properties[IgnoreTilesetFlag]) ) { TiledMapImporter.CurrentRootDir = TiledMapImporter.TmxRootDir; return(null); } Logger.Log("Parsing tileset " + tilesetXml.Attributes["name"].Value); #region Main fields. tileset.Name = tilesetXml.Attributes["name"].Value; tileset.TileWidth = int.Parse(tilesetXml.Attributes["tilewidth"].Value); tileset.TileHeight = int.Parse(tilesetXml.Attributes["tileheight"].Value); tileset.TileCount = int.Parse(tilesetXml.Attributes["tilecount"].Value); tileset.Columns = int.Parse(tilesetXml.Attributes["columns"].Value); tileset.Margin = XmlHelper.GetXmlIntSafe(tilesetXml, "margin"); tileset.Spacing = XmlHelper.GetXmlIntSafe(tilesetXml, "spacing"); if (tilesetXml.Attributes["backgroundcolor"] != null) { tileset.BackgroundColor = XmlHelper.StringToColor(tilesetXml.Attributes["backgroundcolor"].Value); } if (tilesetXml["tileoffset"] != null) { tileset.Offset = new Vector2( float.Parse(tilesetXml["tileoffset"].Attributes["x"].Value, CultureInfo.InvariantCulture), float.Parse(tilesetXml["tileoffset"].Attributes["y"].Value, CultureInfo.InvariantCulture) ); } #endregion Main fields. // Turning tile xml into usable dictionary. var tiles = new Dictionary <int, XmlNode>(); // List won't suit, because some tile ids may be skipped. foreach (XmlNode tileXml in tilesetXml.SelectNodes("tile")) { tiles.Add(int.Parse(tileXml.Attributes["id"].Value), tileXml); } // Turning tile xml into usable dictionary. /* * It is very problematic to load Texture2D without * GraphicsDevice, so textures are imported later as external references. * At this stage map will just remember their * relative paths, and will pick textures up later. */ tileset.Tiles = new TiledMapTilesetTile[tileset.TileCount]; if (tilesetXml["image"] != null) { /* * NOTE: Single image tilesets can still have * <tile> tags with properties. */ // Single-image tileset. var texturePaths = new string[1]; texturePaths[0] = tilesetDir + tilesetXml["image"].Attributes["source"].Value; tileset.TexturePaths = texturePaths; var currentID = 0; for (var y = 0; y < tileset.Height; y += 1) { for (var x = 0; x < tileset.Width; x += 1) { var tile = new TiledMapTilesetTile(); //tile.Tileset = tileset; // Assigning tileset here is useless - loopback link will be lost during serialization. tile.GID = tileset.FirstGID + currentID; tile.TextureID = 0; tile.TexturePosition = new Rectangle( tileset.Margin + x * (tileset.TileWidth + tileset.Spacing), tileset.Margin + y * (tileset.TileHeight + tileset.Spacing), tileset.TileWidth, tileset.TileHeight ); if (tiles.ContainsKey(currentID)) { ReadTileObjects(tiles[currentID], ref tile); tile.Properties = XmlHelper.GetProperties(tiles[currentID]); } else { tile.Objects = new TiledObject[0]; tile.Properties = new Dictionary <string, string>(); } tileset.Tiles[currentID] = tile; currentID += 1; } } // Single-image tileset. } else { // Image collection tileset. var texturePaths = new List <string>(); var currentID = 0; foreach (var nodePair in tiles) { var tile = new TiledMapTilesetTile(); //tile.Tileset = tileset; tile.GID = tileset.FirstGID + nodePair.Key; var texturePath = tilesetDir + nodePair.Value["image"].Attributes["source"].Value; if (texturePaths.Contains(texturePath)) { // Avoiding duplicates. tile.TextureID = texturePaths.IndexOf(texturePath); } else { tile.TextureID = texturePaths.Count; texturePaths.Add(texturePath); } tile.TexturePosition = new Rectangle( 0, 0, int.Parse(nodePair.Value["image"].Attributes["width"].Value), int.Parse(nodePair.Value["image"].Attributes["height"].Value) ); ReadTileObjects(nodePair.Value, ref tile); tile.Properties = XmlHelper.GetProperties(nodePair.Value); tileset.Tiles[currentID] = tile; currentID += 1; } tileset.TexturePaths = texturePaths.ToArray(); // Image collection tileset. } TiledMapImporter.CurrentRootDir = TiledMapImporter.TmxRootDir; return(tileset); }