public Map Load(System.IO.Stream stream) { XmlTextReader xmlReader = new XmlTextReader(stream); xmlReader.WhitespaceHandling = WhitespaceHandling.None; XmlHelper xmlHelper = new XmlHelper(xmlReader); xmlHelper.AdvanceDeclaration(); xmlHelper.AdvanceStartElement("Map"); string mapId = xmlHelper.GetAttribute("Id"); Map map = new Map(mapId); xmlHelper.AdvanceStartElement("Description"); string mapDescription = xmlHelper.GetCData(); xmlHelper.AdvanceEndElement("Description"); map.Description = mapDescription; LoadTileSheets(xmlHelper, map); LoadLayers(xmlHelper, map); LoadProperties(xmlHelper, map); return map; }
private void LoadTileSheets(XmlHelper xmlHelper, Map map) { xmlHelper.AdvanceStartElement("TileSheets"); while (xmlHelper.AdvanceStartRepeatedElement("TileSheet", "TileSheets")) LoadTileSheet(xmlHelper, map); }
private void LoadTileSheet(XmlHelper xmlHelper, Map map) { string id = xmlHelper.GetAttribute("Id"); xmlHelper.AdvanceStartElement("Description"); string description = xmlHelper.GetCData(); xmlHelper.AdvanceEndElement("Description"); xmlHelper.AdvanceStartElement("ImageSource"); string imageSource = xmlHelper.GetCData(); xmlHelper.AdvanceEndElement("ImageSource"); xmlHelper.AdvanceStartElement("Alignment"); Size sheetSize = Size.FromString(xmlHelper.GetAttribute("SheetSize")); Size tileSize = Size.FromString(xmlHelper.GetAttribute("TileSize")); Size margin = Size.FromString(xmlHelper.GetAttribute("Margin")); Size spacing = Size.FromString(xmlHelper.GetAttribute("Spacing")); xmlHelper.AdvanceEndElement("Alignment"); TileSheet tileSheet = new TileSheet(id, map, imageSource, sheetSize, tileSize); tileSheet.Margin = margin; tileSheet.Spacing = spacing; LoadProperties(xmlHelper, tileSheet); xmlHelper.AdvanceEndElement("TileSheet"); map.AddTileSheet(tileSheet); }
private StaticTile LoadStaticTile(XmlHelper xmlHelper, Layer layer, TileSheet tileSheet) { int tileIndex = xmlHelper.GetIntAttribute("Index"); BlendMode blendMode = xmlHelper.GetAttribute("BlendMode") == BlendMode.Alpha.ToString() ? BlendMode.Alpha : BlendMode.Additive; StaticTile staticTile = new StaticTile(layer, tileSheet, blendMode, tileIndex); if (!xmlHelper.XmlReader.IsEmptyElement) { LoadProperties(xmlHelper, staticTile); xmlHelper.AdvanceEndElement("Static"); } return staticTile; }
private void LoadProperties(XmlHelper xmlHelper, Component component) { xmlHelper.AdvanceStartElement("Properties"); while (xmlHelper.AdvanceStartRepeatedElement("Property", "Properties")) { string propertyKey = xmlHelper.GetAttribute("Key"); string propertyType = xmlHelper.GetAttribute("Type"); string propertyValue = xmlHelper.GetCData(); if (propertyType == typeof(bool).Name) component.Properties[propertyKey] = bool.Parse(propertyValue); else if (propertyType == typeof(int).Name) component.Properties[propertyKey] = int.Parse(propertyValue); else if (propertyType == typeof(float).Name) component.Properties[propertyKey] = float.Parse(propertyValue); else component.Properties[propertyKey] = propertyValue; xmlHelper.AdvanceEndElement("Property"); } }
private void LoadLayers(XmlHelper xmlHelper, Map map) { xmlHelper.AdvanceStartElement("Layers"); while (xmlHelper.AdvanceStartRepeatedElement("Layer", "Layers")) LoadLayer(xmlHelper, map); }
private void LoadLayer(XmlHelper xmlHelper, Map map) { string id = xmlHelper.GetAttribute("Id"); bool visible = bool.Parse(xmlHelper.GetAttribute("Visible")); xmlHelper.AdvanceStartElement("Description"); string description = xmlHelper.GetCData(); xmlHelper.AdvanceEndElement("Description"); xmlHelper.AdvanceStartElement("Dimensions"); Size layerSize = Size.FromString(xmlHelper.GetAttribute("LayerSize")); Size tileSize = Size.FromString(xmlHelper.GetAttribute("TileSize")); xmlHelper.AdvanceEndElement("Dimensions"); Layer layer = new Layer(id, map, layerSize, tileSize); layer.Description = description; layer.Visible = visible; xmlHelper.AdvanceStartElement("TileArray"); Location tileLocation = Location.Origin; TileSheet tileSheet = null; XmlReader xmlReader = xmlHelper.XmlReader; while (xmlHelper.AdvanceStartRepeatedElement("Row", "TileArray")) { tileLocation.X = 0; while (xmlHelper.AdvanceNode() != XmlNodeType.EndElement) { if (xmlReader.Name == "Null") { int nullCount = xmlHelper.GetIntAttribute("Count"); tileLocation.X += nullCount % layerSize.Width; } else if (xmlReader.Name == "TileSheet") { string tileSheetRef = xmlHelper.GetAttribute("Ref"); tileSheet = map.GetTileSheet(tileSheetRef); } else if (xmlReader.Name == "Static") { layer.Tiles[tileLocation] = LoadStaticTile(xmlHelper, layer, tileSheet); ++tileLocation.X; } else if (xmlReader.Name == "Animated") { layer.Tiles[tileLocation] = LoadAnimatedTile(xmlHelper, layer, tileSheet); ++tileLocation.X; } } ++tileLocation.Y; } LoadProperties(xmlHelper, layer); xmlHelper.AdvanceEndElement("Layer"); map.AddLayer(layer); }
private AnimatedTile LoadAnimatedTile(XmlHelper xmlHelper, Layer layer, TileSheet tileSheet) { int frameInterval = xmlHelper.GetIntAttribute("Interval"); xmlHelper.AdvanceStartElement("Frames"); Map map = layer.Map; List<StaticTile> tileFrames = new List<StaticTile>(); while (xmlHelper.AdvanceNode() != XmlNodeType.EndElement) { if (xmlHelper.XmlReader.Name == "Static") tileFrames.Add(LoadStaticTile(xmlHelper, layer, tileSheet)); else if (xmlHelper.XmlReader.Name == "TileSheet") { string tileSheetRef = xmlHelper.GetAttribute("Ref"); tileSheet = map.GetTileSheet(tileSheetRef); } } AnimatedTile animatedTile = new AnimatedTile(layer, tileFrames.ToArray(), frameInterval); // end of this element or optional props if (xmlHelper.AdvanceNode() != XmlNodeType.EndElement) LoadProperties(xmlHelper, animatedTile); return animatedTile; }
private void LoadTileSet(XmlHelper xmlHelper, Map map) { string id = xmlHelper.GetAttribute("name"); int firstGid = xmlHelper.GetIntAttribute("firstgid"); int tileWidth = xmlHelper.GetIntAttribute("tilewidth"); int tileHeight = xmlHelper.GetIntAttribute("tileheight"); Size tileSize = new Size(tileWidth, tileHeight); int marginValue = xmlHelper.GetIntAttribute("margin", 0); Size margin = new Size(marginValue); int spacingValue = xmlHelper.GetIntAttribute("spacing", 0); Size spacing = new Size(spacingValue); xmlHelper.AdvanceStartElement("image"); string imageSource = xmlHelper.GetAttribute("source"); xmlHelper.AdvanceEndElement("image"); Size sheetSize = new Size(); try { using (System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(imageSource)) { sheetSize.Width = (bitmap.Width + spacingValue - marginValue) / (tileWidth + spacingValue); sheetSize.Height = (bitmap.Height + spacingValue - marginValue) / (tileHeight + spacingValue); } } catch (Exception exception) { throw new Exception("Unable to determine sheet size from image source", exception); } TileSheet tileSheet = new TileSheet(id, map, imageSource, sheetSize, tileSize); tileSheet.Margin = margin; tileSheet.Spacing = spacing; // keep track of first gid as custom property tileSheet.Properties["@FirstGid"] = firstGid; // also add lastgid to facilitate import tileSheet.Properties["@LastGid"] = firstGid + tileSheet.TileCount - 1; // properties at tile level within tile sets not supported // but are mapped as prefixed properties at tile sheet level XmlNodeType xmlNodeType = xmlHelper.AdvanceNode(); while (xmlNodeType == XmlNodeType.Element && xmlHelper.XmlReader.Name == "tile") { int tileId = xmlHelper.GetIntAttribute("id"); xmlHelper.AdvanceNamedNode(XmlNodeType.Element, "properties"); Component dummyComponent = new DummyComponent(); LoadProperties(xmlHelper, dummyComponent); xmlHelper.AdvanceEndElement("tile"); foreach (string propertyName in dummyComponent.Properties.Keys) { tileSheet.Properties["@Tile@" + tileId + "@" + propertyName] = dummyComponent.Properties[propertyName]; } xmlNodeType = xmlHelper.AdvanceNode(); } map.AddTileSheet(tileSheet); }
private void LoadProperties(XmlHelper xmlHelper, Component component) { while (xmlHelper.AdvanceStartRepeatedElement("property", "properties")) { string propertyKey = xmlHelper.GetAttribute("name"); string propertyValue = xmlHelper.GetAttribute("value"); component.Properties[propertyKey] = propertyValue; xmlHelper.AdvanceEndElement("property"); } }
private void LoadLayerDataXml(XmlHelper xmlHelper, Layer layer) { Location tileLocation = Location.Origin; while (xmlHelper.AdvanceStartRepeatedElement("tile", "data")) { int gid = xmlHelper.GetIntAttribute("gid"); layer.Tiles[tileLocation] = LoadStaticTile(layer, gid); ++tileLocation.X; if (tileLocation.X >= layer.LayerWidth) { tileLocation.X = 0; ++tileLocation.Y; } } }
private void LoadLayerDataCsv(XmlHelper xmlHelper, Layer layer) { xmlHelper.AdvanceNode(XmlNodeType.Text); XmlReader xmlReader = xmlHelper.XmlReader; string csvData = xmlReader.Value; string[] csvElements = csvData.Split(new char[] { ',', '\r', '\n', '\t' }, StringSplitOptions.RemoveEmptyEntries); Location tileLocation = Location.Origin; foreach (string csvElement in csvElements) { int gid = int.Parse(csvElement); layer.Tiles[tileLocation] = LoadStaticTile(layer, gid); ++tileLocation.X; if (tileLocation.X >= layer.LayerWidth) { tileLocation.X = 0; ++tileLocation.Y; } } xmlHelper.AdvanceEndElement("data"); }
private void LoadLayerDataBase64(XmlHelper xmlHelper, Layer layer, string dataCompression) { xmlHelper.AdvanceNode(XmlNodeType.Text); string base64Data = xmlHelper.XmlReader.Value; byte[] dataBytes = System.Convert.FromBase64String(base64Data); if (dataCompression == "none") { // do nothing } else if (dataCompression == "gzip") { GZipStream inGZipStream = new GZipStream( new MemoryStream(dataBytes), CompressionMode.Decompress); MemoryStream outMemoryStream = new MemoryStream(); byte[] buffer = new byte[1024]; while (true) { int bytesRead = inGZipStream.Read(buffer, 0, buffer.Length); if (bytesRead == 0) break; outMemoryStream.Write(buffer, 0, bytesRead); } dataBytes = outMemoryStream.ToArray(); } else if (dataCompression == "zlib") { ZInputStream inZInputStream = new ZInputStream( new MemoryStream(dataBytes)); MemoryStream outMemoryStream = new MemoryStream(); byte[] buffer = new byte[1024]; while (true) { int bytesRead = inZInputStream.Read(buffer, 0, buffer.Length); if (bytesRead == 0) break; outMemoryStream.Write(buffer, 0, bytesRead); } dataBytes = outMemoryStream.ToArray(); } else throw new Exception("Unknown compression scheme: " + dataCompression); if (dataBytes.Length % 4 != 0) throw new Exception("Base64 byte stream size must be a mutliple of 4 bytes"); Location tileLocation = Location.Origin; for (int byteIndex = 0; byteIndex < dataBytes.Length; byteIndex += 4) { int gid = dataBytes[byteIndex] | dataBytes[byteIndex + 1] << 8 | dataBytes[byteIndex + 2] << 16 | dataBytes[byteIndex + 3] << 24; layer.Tiles[tileLocation] = LoadStaticTile(layer, gid); ++tileLocation.X; if (tileLocation.X >= layer.LayerWidth) { tileLocation.X = 0; ++tileLocation.Y; } } xmlHelper.AdvanceEndElement("data"); }
private void LoadLayer(XmlHelper xmlHelper, Map map) { if (map.TileSheets.Count == 0) throw new Exception("Must load at least one tileset to determine layer tile size"); string id = xmlHelper.GetAttribute("name"); int layerWidth = xmlHelper.GetIntAttribute("width"); int layerHeight = xmlHelper.GetIntAttribute("height"); Size layerSize = new Size(layerWidth, layerHeight); int visible = xmlHelper.GetIntAttribute("visible", 1); // must assume tile size from first tile set Size tileSize = map.TileSheets[0].TileSize; Layer layer = new Layer(id, map, layerSize, tileSize); layer.Visible = visible > 0; // load properties if available XmlNodeType xmlNodeType = xmlHelper.AdvanceNode(); if (xmlNodeType == XmlNodeType.Element && xmlHelper.XmlReader.Name == "properties") { LoadProperties(xmlHelper, layer); // try to obtain layer description via custom property if (layer.Properties.ContainsKey("@Description")) layer.Description = layer.Properties["@Description"]; xmlHelper.AdvanceStartElement("data"); } else if (xmlNodeType != XmlNodeType.Element || xmlHelper.XmlReader.Name != "data") throw new Exception("The element <properties> or <data> expected"); string dataEncoding = xmlHelper.GetAttribute("encoding", "xml"); string dataCompression = xmlHelper.GetAttribute("compression", "none"); if (dataEncoding == "xml") LoadLayerDataXml(xmlHelper, layer); else if (dataEncoding == "base64") LoadLayerDataBase64(xmlHelper, layer, dataCompression); else if (dataEncoding == "csv") LoadLayerDataCsv(xmlHelper, layer); else throw new Exception("Unknown encoding/compression setting combination (" + dataEncoding + "/" + dataCompression + ")"); xmlHelper.AdvanceEndElement("layer"); map.AddLayer(layer); }
public Map Load(Stream stream) { XmlTextReader xmlReader = new XmlTextReader(stream); xmlReader.WhitespaceHandling = WhitespaceHandling.None; XmlHelper xmlHelper = new XmlHelper(xmlReader); xmlHelper.AdvanceDeclaration(); xmlHelper.AdvanceStartElement("map"); string orientation = xmlHelper.GetAttribute("orientation"); if (orientation != "orthogonal") throw new Exception("Only orthogonal Tiled maps are supported."); int mapWidth = xmlHelper.GetIntAttribute("width"); int mapHeight = xmlHelper.GetIntAttribute("height"); int tileWidth = xmlHelper.GetIntAttribute("tilewidth"); int tileHeight = xmlHelper.GetIntAttribute("tileheight"); Map map = new Map(); while (true) { XmlNodeType xmlNodeType = xmlHelper.AdvanceNode(); if (xmlNodeType == XmlNodeType.EndElement) break; if (xmlReader.Name == "properties") LoadProperties(xmlHelper, map); else if (xmlReader.Name == "tileset") LoadTileSet(xmlHelper, map); else if (xmlReader.Name == "layer") LoadLayer(xmlHelper, map); else xmlHelper.SkipToEndElement(xmlReader.Name); } // try to obtain map description via custom property if (map.Properties.ContainsKey("@Description")) map.Description = map.Properties["@Description"]; return map; }
private void LoadLayer(XmlHelper xmlHelper, Map map) { string id = xmlHelper.GetAttribute("Id"); bool visible = bool.Parse(xmlHelper.GetAttribute("Visible")); xmlHelper.AdvanceStartElement("Description"); string description = xmlHelper.GetCData(); xmlHelper.AdvanceEndElement("Description"); xmlHelper.AdvanceStartElement("Dimensions"); Size layerSize = Size.FromString(xmlHelper.GetAttribute("LayerSize")); Size tileSize = Size.FromString(xmlHelper.GetAttribute("TileSize")); xmlHelper.AdvanceEndElement("Dimensions"); Layer layer = new Layer(id, map, layerSize, tileSize); layer.Description = description; layer.Visible = visible; xmlHelper.AdvanceStartElement("TileData"); string tileSheetId = xmlHelper.GetAttribute("TileSheet"); string layerFilename = xmlHelper.GetAttribute("Filename"); xmlHelper.AdvanceEndElement("TileData"); TileSheet tileSheet = map.GetTileSheet(tileSheetId); if (tileSheet == null) throw new Exception("Invalid tile sheet reference: " + tileSheetId); TextReader layerTextReader = new StreamReader(layerFilename); int tileY = 0; char[] commas = new char[]{','}; while (tileY < layer.LayerHeight) { string layerLine = layerTextReader.ReadLine(); if (layerLine == null) break; string[] tokens = layerLine.Split(commas); int tileX = 0; foreach (string token in tokens) { if (tileX >= layer.LayerWidth) break; int tileIndex = int.Parse(token.Trim()); layer.Tiles[tileX++, tileY] = new StaticTile(layer, tileSheet, BlendMode.Alpha, tileIndex); } ++tileY; } layerTextReader.Close(); LoadProperties(xmlHelper, layer); xmlHelper.AdvanceEndElement("Layer"); map.AddLayer(layer); }