public override TmxMap Import(string filename, ContentImporterContext context) { if (filename == null) { throw new ArgumentNullException(nameof(filename)); } var mapSerializer = new XmlSerializer(typeof(TmxMap)); var tileSetSerializer = new XmlSerializer(typeof(TmxTileSet)); var map = (TmxMap)mapSerializer.Deserialize(new StringReader(File.ReadAllText(filename))); map.OriginalFileName = filename; for (var i = 0; i < map.TileSets.Count; i++) { var baseReferenceFile = filename; if (!string.IsNullOrWhiteSpace(map.TileSets[i].Source)) { var tileSetPath = ImportPathHelper.GetReferencedFilePath( filename, map.TileSets[i].Source); context.AddDependency(tileSetPath); var originalFirstGid = map.TileSets[i].FirstGid; map.TileSets[i] = (TmxTileSet)tileSetSerializer.Deserialize(new StringReader(File.ReadAllText(tileSetPath))); map.TileSets[i].FirstGid = originalFirstGid; baseReferenceFile = tileSetPath; } if (map.TileSets[i].Image != null) { map.TileSets[i].Image.Source = ImportPathHelper.GetReferencedFilePath( baseReferenceFile, map.TileSets[i].Image.Source); context.AddDependency(map.TileSets[i].Image.Source); } foreach (var tile in map.TileSets[i].Tiles) { if (tile.Image != null) { tile.Image.Source = ImportPathHelper.GetReferencedFilePath( baseReferenceFile, tile.Image.Source); } } } foreach (var layer in map.Layers.OfType <TmxTileLayer>()) { var data = layer.Data; if (data.Encoding == "csv") { data.Tiles = data.Value.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries) .Select(uint.Parse).Select(gid => new TmxDataTile { Gid = gid }).ToList(); } else if (data.Encoding == "base64") { var encodedData = data.Value.Trim(); var decodedData = Convert.FromBase64String(encodedData); using (var stream = OpenStream(decodedData, data.Compression)) using (var reader = new BinaryReader(stream)) { data.Tiles = new List <TmxDataTile>(); for (var y = 0; y < layer.Width; y++) { for (var x = 0; x < layer.Height; x++) { var gid = reader.ReadUInt32(); data.Tiles.Add(new TmxDataTile { Gid = gid }); } } } } } foreach (var layer in map.Layers.OfType <TmxImageLayer>()) { if (layer.Image != null) { layer.Image.Source = ImportPathHelper.GetReferencedFilePath( filename, layer.Image.Source); } } return(map); }
public override TiledMap Process(TmxMap input, ContentProcessorContext context) { foreach (var tileSet in input.TileSets) { if (tileSet.Image == null) { var images = new HashSet <string>(); foreach (var tile in tileSet.Tiles) { if (tile.Image != null) { images.Add(tile.Image.Source); } } context.Logger.LogMessage("Packing {0} images\n", images.Count); var bitmaps = new Dictionary <string, Bitmap>(); foreach (var image in images) { bitmaps.Add(image, new Bitmap(image)); } var packedSprites = TextureAtlasPacker.PackSprites(bitmaps.Values.ToList()); var atlasPath = input.OriginalFileName + "-atlas.png"; packedSprites.OutputBitmap.Save(atlasPath, System.Drawing.Imaging.ImageFormat.Png); var assetFileName = context.BuildAsset <string, Texture2DContent>( new ExternalReference <string>(atlasPath), nameof(TextureProcessor)).Filename; tileSet.Image = new TmxImage { Source = ImportPathHelper.GetAssetName(context.OutputDirectory, assetFileName) }; File.Delete(atlasPath); foreach (var tile in tileSet.Tiles) { if (tile.Image == null) { continue; } var rect = packedSprites.SpritePositions[bitmaps[tile.Image.Source]]; tile.SourceRect = new Rectangle(rect.X, rect.Y, rect.Width, rect.Height); } } else { var assetFileName = context.BuildAsset <string, Texture2DContent>( new ExternalReference <string>(tileSet.Image.Source), nameof(TextureProcessor)).Filename; tileSet.Image.Source = ImportPathHelper.GetAssetName(context.OutputDirectory, assetFileName); } } foreach (var layer in input.Layers.OfType <TmxImageLayer>()) { if (layer.Image != null) { var assetFileName = context.BuildAsset <string, Texture2DContent>( new ExternalReference <string>(layer.Image.Source), nameof(TextureProcessor)).Filename; layer.Image.Source = ImportPathHelper.GetAssetName(context.OutputDirectory, assetFileName); } } var output = new TiledMap { FirstGid = input.FirstGid, Width = input.Width, Height = input.Height, TileWidth = input.TileWidth, TileHeight = input.TileHeight, Orientation = (TiledMapOrientation)input.Orientation, BackgroundColor = HexToColor(input.BackgroundColor), RenderOrder = (TiledRenderOrder)input.RenderOrder, Properties = input.Properties?.ToDictionary(a => a.Name, a => a.Value), ObjectGroups = input.ObjectGroups?.Select( a => new TiledObjectGroup { Name = a.Name, Color = HexToColor(a.Color), Opacity = a.Opacity, Visible = a.Visible, Properties = a.Properties?.ToDictionary(b => b.Name, b => b.Value), Objects = a.Objects?.Select( b => { var tiledObject = new TiledObject { Id = b.Id, Name = b.Name, Type = b.Type, X = (int)b.X, Y = (int)b.Y, Width = (int)b.Width, Height = (int)b.Height, Rotation = b.Rotation, Gid = b.Gid, Visible = b.Visible, Properties = b.Properties?.ToDictionary(c => c.Name, c => c.Value), ObjectType = b.Type, }; if (b.Ellipse != null) { tiledObject.TiledObjectType = TiledObject.TiledObjectTypes.Ellipse; } else if (b.Image != null) { tiledObject.TiledObjectType = TiledObject.TiledObjectTypes.Image; } else if (b.Polygon != null) { tiledObject.TiledObjectType = TiledObject.TiledObjectTypes.Polygon; tiledObject.PolyPoints = GetPoints(b.Polygon.Points); } else if (b.PolyLine != null) { tiledObject.TiledObjectType = TiledObject.TiledObjectTypes.Polyline; tiledObject.PolyPoints = GetPoints(b.PolyLine.Points); } else { tiledObject.TiledObjectType = TiledObject.TiledObjectTypes.None; } return(tiledObject); }).ToList() }).ToList(), TileSets = input.TileSets?.Select( a => { var tileSet = TiledTileSet.Build(a.Image.Width, a.Image.Height, a.TileWidth, a.TileHeight, a.Spacing, a.Margin, a.Columns); tileSet.FirstGid = a.FirstGid; tileSet.Image = a.Image.Source; tileSet.Properties = a.Properties.ToDictionary(b => b.Name, b => b.Value); foreach (var tile in a.Tiles) { var tiledTile = tileSet.Tiles.FirstOrDefault(b => b.Id == tile.Id); if (tiledTile == null) { tiledTile = new TiledTileSetTile { Id = tile.Id }; tileSet.Tiles.Add(tiledTile); } tiledTile.SourceRect = tile.SourceRect != Rectangle.Empty ? tile.SourceRect : tiledTile.SourceRect; tiledTile.AnimationFrames = tile.AnimationFrames == null || tile.AnimationFrames.Count == 0 ? null : tile.AnimationFrames.Select(b => new TiledTileSetAnimationFrame { TileId = b.TileId, Duration = b.Duration }).ToList(); tile.Properties.ForEach(b => tiledTile.Properties[b.Name] = b.Value); } return(tileSet); }).ToList() }; var existingIds = output.TileSets.SelectMany(a => a.Tiles.Select(b => (uint)(b.Id + a.FirstGid))).ToHashSet(); output.Layers = input.Layers?.Select( a => { var imageLayer = a as TmxImageLayer; var tiledLayer = a as TmxTileLayer; TiledLayer result; if (imageLayer != null) { result = new TiledImageLayer { AssetName = imageLayer.Image.Source }; } else if (tiledLayer != null) { result = new TiledTileLayer { Width = tiledLayer.Width, Height = tiledLayer.Height, X = tiledLayer.X, Y = tiledLayer.Y, Tiles = tiledLayer.Data.Tiles.Select( b => { var flippedHorizontally = (b.Gid & FlippedHorizontallyFlag) != 0; var flippedVertically = (b.Gid & FlippedVerticallyFlag) != 0; var flippedDiagonally = (b.Gid & FlippedDiagonallyFlag) != 0; if (flippedHorizontally || flippedVertically || flippedDiagonally) { b.Gid &= ~(FlippedHorizontallyFlag | FlippedVerticallyFlag | FlippedDiagonallyFlag); b.FlippedHorizontally = flippedHorizontally; b.FlippedVertically = flippedVertically; b.FlippedDiagonally = flippedDiagonally; } if (!existingIds.Contains(b.Gid)) { return(null); } return(new TiledTile { Id = (int)b.Gid, FlippedDiagonally = b.FlippedDiagonally, FlippedHorizonally = b.FlippedHorizontally, FlippedVertically = b.FlippedVertically, }); }).ToArray() }; } else { throw new Exception($"Unknown layer type {a.GetType()}"); } result.Name = a.Name; result.Offset = new Vector2(a.OffsetX, a.OffsetY); result.Opacity = a.Opacity; result.Visible = a.Visible; result.Properties = a.Properties.ToDictionary(b => b.Name, b => b.Value); return(result); }).ToList(); return(output); }