예제 #1
0
        static void setTilesetTextureIfNecessary(TmxTileset tileset, ContentProcessorContext context)
        {
            if (tileset.image != null)
            {
                return;
            }

            tileset.isStandardTileset = false;

            var imagePaths = new List <string>();

            foreach (var tile in tileset.tiles)
            {
                if (tile.image != null && !imagePaths.Contains(tile.image.source))
                {
                    imagePaths.Add(tile.image.source);
                }
            }

            context.Logger.LogMessage("\n\t --- need to pack images: {0}\n", imagePaths.Count);
            var sourceSprites = new List <BitmapContent>();

            // Loop over each input sprite filename
            foreach (var inputFilename in imagePaths)
            {
                // Store the name of this sprite.
                var spriteName = Path.GetFileName(inputFilename);

                var absolutePath = PathHelper.getAbsolutePath(inputFilename, tileset.mapFolder);
                context.Logger.LogMessage("Adding texture: {0}", spriteName);

                // Load the sprite texture into memory.
                var textureReference = new ExternalReference <TextureContent>(absolutePath);
                var texture          = context.BuildAndLoadAsset <TextureContent, TextureContent>(textureReference, "TextureProcessor");

                sourceSprites.Add(texture.Faces[0][0]);
            }

            var spriteRectangles = new List <Rectangle>();

            // pack all the sprites into a single large texture.
            var packedSprites = TextureAtlasPacker.packSprites(sourceSprites, spriteRectangles, false, context);

            context.Logger.LogMessage("packed: {0}", packedSprites);

            // save out a PNG with our atlas
            var bm = new System.Drawing.Bitmap(packedSprites.Width, packedSprites.Height);

            for (var x = 0; x < packedSprites.Width; x++)
            {
                for (var y = 0; y < packedSprites.Height; y++)
                {
                    var col   = packedSprites.GetPixel(x, y);
                    var color = System.Drawing.Color.FromArgb(col.A, col.R, col.G, col.B);
                    bm.SetPixel(x, y, color);
                }
            }

            var atlasFilename = tileset.name + "-atlas.png";

            bm.Save(Path.Combine(tileset.mapFolder, atlasFilename), System.Drawing.Imaging.ImageFormat.Png);
            context.Logger.LogImportantMessage("\n-- generated atlas {0}. Make sure you add it to the Pipeline tool!", atlasFilename);

            // set the new atlas as our tileset source image
            tileset.image        = new TmxImage();
            tileset.image.source = atlasFilename;

            // last step: set the new atlas info and source rectangle for each tile
            foreach (var tile in tileset.tiles)
            {
                if (tile.image == null)
                {
                    continue;
                }

                tile.sourceRect = spriteRectangles[imagePaths.IndexOf(tile.image.source)];
            }
        }
예제 #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);
        }