/// <summary> /// Checks is a tile is flipped diagonally /// </summary> /// <param name="layer">An entry of the TiledMap.layers array</param> /// <param name="dataIndex">An index of the TiledLayer.data array</param> /// <returns>True if the tile was flipped diagonally or False if not</returns> public bool IsTileFlippedDiagonal(TiledLayer layer, int dataIndex) { return((layer.dataRotationFlags[dataIndex] & (FLIPPED_DIAGONALLY_FLAG >> SHIFT_FLIP_FLAG_TO_BYTE)) > 0); }
/// <summary> /// Checks is a tile is flipped diagonally /// </summary> /// <param name="layer">An entry of the TiledMap.layers array</param> /// <param name="tileHor">The tile's horizontal position</param> /// <param name="tileVert">The tile's vertical position</param> /// <returns>True if the tile was flipped diagonally or False if not</returns> public bool IsTileFlippedDiagonal(TiledLayer layer, int tileHor, int tileVert) { return(IsTileFlippedDiagonal(layer, tileHor + (tileVert * layer.width))); }
/// <summary> /// Checks is a tile is flipped horizontally /// </summary> /// <param name="layer">An entry of the TiledMap.layers array</param> /// <param name="dataIndex">An index of the TiledLayer.data array</param> /// <returns>True if the tile was flipped horizontally or False if not</returns> public bool IsTileFlippedHorizontal(TiledLayer layer, int dataIndex) { return((layer.dataRotationFlags[dataIndex] & (FLIPPED_HORIZONTALLY_FLAG >> SHIFT_FLIP_FLAG_TO_BYTE)) > 0); }
/// <summary> /// Checks is a tile is flipped vertically /// </summary> /// <param name="layer">An entry of the TiledMap.layers array</param> /// <param name="dataIndex">An index of the TiledLayer.data array</param> /// <returns>True if the tile was flipped vertically or False if not</returns> public bool IsTileFlippedVertical(TiledLayer layer, int dataIndex) { return((layer.dataRotationFlags[dataIndex] & (FLIPPED_VERTICALLY_FLAG >> SHIFT_FLIP_FLAG_TO_BYTE)) > 0); }
private TiledLayer[] ParseLayers(XmlNodeList nodesLayer, XmlNodeList nodesObjectGroup, XmlNodeList nodesImageLayer) { var result = new List <TiledLayer>(); foreach (XmlNode node in nodesLayer) { var nodeData = node.SelectSingleNode("data"); var nodesProperty = node.SelectNodes("properties/property"); var encoding = nodeData.Attributes["encoding"].Value; var attrVisible = node.Attributes["visible"]; var attrLocked = node.Attributes["locked"]; var attrTint = node.Attributes["tintcolor"]; var attrOffsetX = node.Attributes["offsetx"]; var attrOffsetY = node.Attributes["offsety"]; var tiledLayer = new TiledLayer(); tiledLayer.id = int.Parse(node.Attributes["id"].Value); tiledLayer.name = node.Attributes["name"].Value; tiledLayer.height = int.Parse(node.Attributes["height"].Value); tiledLayer.width = int.Parse(node.Attributes["width"].Value); tiledLayer.type = "tilelayer"; tiledLayer.visible = true; if (attrVisible != null) { tiledLayer.visible = attrVisible.Value == "1"; } if (attrLocked != null) { tiledLayer.locked = attrLocked.Value == "1"; } if (attrTint != null) { tiledLayer.tintcolor = attrTint.Value; } if (attrOffsetX != null) { tiledLayer.offsetX = int.Parse(attrOffsetX.Value); } if (attrOffsetY != null) { tiledLayer.offsetY = int.Parse(attrOffsetY.Value); } if (nodesProperty != null) { tiledLayer.properties = ParseProperties(nodesProperty); } if (encoding == "csv") { var csvs = nodeData.InnerText.Split(','); tiledLayer.data = new int[csvs.Length]; tiledLayer.dataRotationFlags = new byte[csvs.Length]; // Parse the comma separated csv string and update the inner data as well as the data rotation flags for (var i = 0; i < csvs.Length; i++) { var rawID = uint.Parse(csvs[i]); var hor = ((rawID & FLIPPED_HORIZONTALLY_FLAG)); var ver = ((rawID & FLIPPED_VERTICALLY_FLAG)); var dia = ((rawID & FLIPPED_DIAGONALLY_FLAG)); tiledLayer.dataRotationFlags[i] = (byte)((hor | ver | dia) >> SHIFT_FLIP_FLAG_TO_BYTE); // assign data to rawID with the rotation flags cleared tiledLayer.data[i] = (int)(rawID & ~(FLIPPED_HORIZONTALLY_FLAG | FLIPPED_VERTICALLY_FLAG | FLIPPED_DIAGONALLY_FLAG)); } } else if (encoding == "base64") { var compression = nodeData.Attributes["compression"]?.Value; using (var base64DataStream = new MemoryStream(Convert.FromBase64String(nodeData.InnerText))) { if (compression == null) { // Parse the decoded bytes and update the inner data as well as the data rotation flags var rawBytes = new byte[4]; tiledLayer.data = new int[base64DataStream.Length]; tiledLayer.dataRotationFlags = new byte[base64DataStream.Length]; for (var i = 0; i < base64DataStream.Length; i++) { base64DataStream.Read(rawBytes, 0, rawBytes.Length); var rawID = BitConverter.ToUInt32(rawBytes, 0); var hor = ((rawID & FLIPPED_HORIZONTALLY_FLAG)); var ver = ((rawID & FLIPPED_VERTICALLY_FLAG)); var dia = ((rawID & FLIPPED_DIAGONALLY_FLAG)); tiledLayer.dataRotationFlags[i] = (byte)((hor | ver | dia) >> SHIFT_FLIP_FLAG_TO_BYTE); // assign data to rawID with the rotation flags cleared tiledLayer.data[i] = (int)(rawID & ~(FLIPPED_HORIZONTALLY_FLAG | FLIPPED_VERTICALLY_FLAG | FLIPPED_DIAGONALLY_FLAG)); } } else if (compression == "zlib") { // .NET doesn't play well with the headered zlib data that Tiled produces, // so we have to manually skip the 2-byte header to get what DeflateStream's looking for // Should an external library be used instead of this hack? base64DataStream.ReadByte(); base64DataStream.ReadByte(); using (var decompressionStream = new DeflateStream(base64DataStream, CompressionMode.Decompress)) { // Parse the raw decompressed bytes and update the inner data as well as the data rotation flags var decompressedDataBuffer = new byte[4]; // size of each tile var dataRotationFlagsList = new List <byte>(); var layerDataList = new List <int>(); while (decompressionStream.Read(decompressedDataBuffer, 0, decompressedDataBuffer.Length) == decompressedDataBuffer.Length) { var rawID = BitConverter.ToUInt32(decompressedDataBuffer, 0); var hor = ((rawID & FLIPPED_HORIZONTALLY_FLAG)); var ver = ((rawID & FLIPPED_VERTICALLY_FLAG)); var dia = ((rawID & FLIPPED_DIAGONALLY_FLAG)); dataRotationFlagsList.Add((byte)((hor | ver | dia) >> SHIFT_FLIP_FLAG_TO_BYTE)); // assign data to rawID with the rotation flags cleared layerDataList.Add((int)(rawID & ~(FLIPPED_HORIZONTALLY_FLAG | FLIPPED_VERTICALLY_FLAG | FLIPPED_DIAGONALLY_FLAG))); } tiledLayer.data = layerDataList.ToArray(); tiledLayer.dataRotationFlags = dataRotationFlagsList.ToArray(); } } else if (compression == "gzip") { using (var decompressionStream = new GZipStream(base64DataStream, CompressionMode.Decompress)) { // Parse the raw decompressed bytes and update the inner data as well as the data rotation flags var decompressedDataBuffer = new byte[4]; // size of each tile var dataRotationFlagsList = new List <byte>(); var layerDataList = new List <int>(); while (decompressionStream.Read(decompressedDataBuffer, 0, decompressedDataBuffer.Length) == decompressedDataBuffer.Length) { var rawID = BitConverter.ToUInt32(decompressedDataBuffer, 0); var hor = ((rawID & FLIPPED_HORIZONTALLY_FLAG)); var ver = ((rawID & FLIPPED_VERTICALLY_FLAG)); var dia = ((rawID & FLIPPED_DIAGONALLY_FLAG)); dataRotationFlagsList.Add((byte)((hor | ver | dia) >> SHIFT_FLIP_FLAG_TO_BYTE)); // assign data to rawID with the rotation flags cleared layerDataList.Add((int)(rawID & ~(FLIPPED_HORIZONTALLY_FLAG | FLIPPED_VERTICALLY_FLAG | FLIPPED_DIAGONALLY_FLAG))); } tiledLayer.data = layerDataList.ToArray(); tiledLayer.dataRotationFlags = dataRotationFlagsList.ToArray(); } } else { throw new TiledException("Zstandard compression is currently not supported"); } } } else { throw new TiledException("Only CSV and Base64 encodings are currently supported"); } result.Add(tiledLayer); } foreach (XmlNode node in nodesObjectGroup) { var nodesProperty = node.SelectNodes("properties/property"); var nodesObject = node.SelectNodes("object"); var attrVisible = node.Attributes["visible"]; var attrLocked = node.Attributes["locked"]; var attrTint = node.Attributes["tintcolor"]; var attrOffsetX = node.Attributes["offsetx"]; var attrOffsetY = node.Attributes["offsety"]; var tiledLayer = new TiledLayer(); tiledLayer.id = int.Parse(node.Attributes["id"].Value); tiledLayer.name = node.Attributes["name"].Value; tiledLayer.objects = ParseObjects(nodesObject); tiledLayer.type = "objectgroup"; tiledLayer.visible = true; if (attrVisible != null) { tiledLayer.visible = attrVisible.Value == "1"; } if (attrLocked != null) { tiledLayer.locked = attrLocked.Value == "1"; } if (attrTint != null) { tiledLayer.tintcolor = attrTint.Value; } if (attrOffsetX != null) { tiledLayer.offsetX = int.Parse(attrOffsetX.Value); } if (attrOffsetY != null) { tiledLayer.offsetY = int.Parse(attrOffsetY.Value); } if (nodesProperty != null) { tiledLayer.properties = ParseProperties(nodesProperty); } result.Add(tiledLayer); } foreach (XmlNode node in nodesImageLayer) { var nodesProperty = node.SelectNodes("properties/property"); var nodeImage = node.SelectSingleNode("image"); var attrVisible = node.Attributes["visible"]; var attrLocked = node.Attributes["locked"]; var attrTint = node.Attributes["tintcolor"]; var attrOffsetX = node.Attributes["offsetx"]; var attrOffsetY = node.Attributes["offsety"]; var tiledLayer = new TiledLayer(); tiledLayer.id = int.Parse(node.Attributes["id"].Value); tiledLayer.name = node.Attributes["name"].Value; tiledLayer.type = "imagelayer"; tiledLayer.visible = true; if (attrVisible != null) { tiledLayer.visible = attrVisible.Value == "1"; } if (attrLocked != null) { tiledLayer.locked = attrLocked.Value == "1"; } if (attrTint != null) { tiledLayer.tintcolor = attrTint.Value; } if (attrOffsetX != null) { tiledLayer.offsetX = int.Parse(attrOffsetX.Value); } if (attrOffsetY != null) { tiledLayer.offsetY = int.Parse(attrOffsetY.Value); } if (nodesProperty != null) { tiledLayer.properties = ParseProperties(nodesProperty); } if (nodeImage != null) { tiledLayer.image = ParseImage(nodeImage); } result.Add(tiledLayer); } return(result.ToArray()); }