Пример #1
0
        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);
        }
Пример #2
0
        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);
        }