Esempio n. 1
0
        private SpriteSave CreateSpriteSaveFromMapTileset(float scale, int layercount, MapLayer mapLayer, int tileIndex, uint gid, Tileset tileSet, FileReferenceType referenceType = FileReferenceType.NoDirectory)
        {
            var sprite = new SpriteSave();

            if (!mapLayer.IsVisible && mapLayer.VisibleBehavior == LayerVisibleBehavior.Match)
            {
                sprite.Visible = false;
            }

            int imageWidth  = tileSet.Images[0].width;
            int imageHeight = tileSet.Images[0].height;
            int tileWidth   = tileSet.Tilewidth;
            int spacing     = tileSet.Spacing;
            int tileHeight  = tileSet.Tileheight;
            int margin      = tileSet.Margin;

            // TODO: only calculate these once per tileset. Perhaps it can be done in the deserialize method
            //int tilesWide = (imageWidth - margin) / (tileWidth + spacing);
            //int tilesHigh = (imageHeight - margin) / (tileHeight + spacing);

            if (referenceType == FileReferenceType.NoDirectory)
            {
                sprite.Texture = tileSet.Images[0].sourceFileName;
            }
            else if (referenceType == FileReferenceType.Absolute)
            {
                string directory = FileManager.GetDirectory(this.FileName);

                if (!string.IsNullOrEmpty(tileSet.SourceDirectory) && tileSet.SourceDirectory != ".")
                {
                    directory += tileSet.SourceDirectory;

                    directory = FileManager.RemoveDotDotSlash(directory);
                }

                sprite.Texture = FileManager.RemoveDotDotSlash(directory + tileSet.Images[0].Source);
            }
            else
            {
                throw new NotImplementedException();
            }

            uint tileTextureRelativeToStartOfTileset =
                (0x0fffffff & gid) - tileSet.Firstgid + 1;

            if (tileSet.TileDictionary.ContainsKey(tileTextureRelativeToStartOfTileset))
            {
                var dictionary = tileSet.TileDictionary[tileTextureRelativeToStartOfTileset].PropertyDictionary;

                foreach (var kvp in dictionary)
                {
                    var key = kvp.Key;

                    if (IsName(key))
                    {
                        sprite.Name = kvp.Value;
                    }
                }
            }

            if (string.IsNullOrEmpty(sprite.Name))
            {
                sprite.Name = "Unnamed" + gid;
            }

            SetSpriteTextureCoordinates(gid, sprite, tileSet);
            CalculateWorldCoordinates(layercount, tileIndex, tileWidth, tileHeight, this.Width, out sprite.X, out sprite.Y, out sprite.Z);

            sprite.ScaleX = tileWidth / 2.0f;
            sprite.ScaleY = tileHeight / 2.0f;

            if (tileSet.Tileoffset != null && tileSet.Tileoffset.Length == 1)
            {
                sprite.X += tileSet.Tileoffset[0].x;
                sprite.Y -= tileSet.Tileoffset[0].y;
            }


            sprite.X *= scale;
            sprite.Y *= scale;
            // Update August 28, 2012
            // The TMX converter splits
            // the Layers by their Z values.
            // We want each Layer to have its
            // own explicit Z value, so we don't
            // want to adjust the Z's when we scale:
            //sprite.Z *= scale;

            sprite.ScaleX *= scale;
            sprite.ScaleY *= scale;
            return(sprite);
        }
        /// <summary>
        /// Converts a TiledMapSave to a ReducedTileMapInfo object
        /// </summary>
        /// <param name="tiledMapSave">The TiledMapSave to convert</param>
        /// <param name="scale">The amount to scale by - default of 1</param>
        /// <param name="zOffset">The zOffset</param>
        /// <param name="directory">The directory of the file associated with the tiledMapSave, used to find file references.</param>
        /// <param name="referenceType">How the files in the .tmx are referenced.</param>
        /// <returns></returns>
        public static ReducedTileMapInfo FromTiledMapSave(TiledMapSave tiledMapSave, float scale, float zOffset, string directory, FileReferenceType referenceType)
        {
            var toReturn = new ReducedTileMapInfo
            {
                NumberCellsTall = tiledMapSave.Height,
                NumberCellsWide = tiledMapSave.Width
            };


            var ses = tiledMapSave.ToSceneSave(scale, referenceType);

            // This is not a stable sort!
            //ses.SpriteList.Sort((first, second) => first.Z.CompareTo(second.Z));
            ses.SpriteList = ses.SpriteList.OrderBy(item => item.Z).ToList();

            ReducedLayerInfo reducedLayerInfo = null;

            // If we rely on the image, it's both slow (have to open the images), and
            // doesn't work at runtime in games:
            //Dictionary<string, Point> loadedTextures = new Dictionary<string, Point>();
            //SetCellWidthAndHeight(tiledMapSave, directory, toReturn, ses, loadedTextures);

            toReturn.CellHeightInPixels = (ushort)tiledMapSave.tileheight;
            toReturn.CellWidthInPixels = (ushort)tiledMapSave.tilewidth;


            SetQuadWidthAndHeight(toReturn, ses);

            float z = float.NaN;


            int textureWidth = 0;
            int textureHeight = 0;

            AbstractMapLayer currentLayer = null;
            int indexInLayer = 0;


            foreach (var spriteSave in ses.SpriteList)
            {
                if (spriteSave.Z != z)
                {
                    indexInLayer = 0;
                    z = spriteSave.Z;


                    int layerIndex = FlatRedBall.Math.MathFunctions.RoundToInt(z - zOffset);
                    var abstractMapLayer = tiledMapSave.MapLayers[layerIndex];
                    currentLayer = abstractMapLayer;

                    reducedLayerInfo = new ReducedLayerInfo
                    {
                        Z = spriteSave.Z,
                        Texture = spriteSave.Texture,
                        Name = abstractMapLayer.Name,
                        TileWidth = FlatRedBall.Math.MathFunctions.RoundToInt(spriteSave.ScaleX * 2),
                        TileHeight = FlatRedBall.Math.MathFunctions.RoundToInt(spriteSave.ScaleY * 2)
                    };

                    var mapLayer = abstractMapLayer as MapLayer;
                    // This should have data:
                    if (mapLayer != null)
                    {
                        var idOfTexture = mapLayer.data[0].tiles.FirstOrDefault(item => item != 0);
                        Tileset tileSet = tiledMapSave.GetTilesetForGid(idOfTexture);
                        var tilesetIndex = tiledMapSave.Tilesets.IndexOf(tileSet);

                        textureWidth = tileSet.Images[0].width;
                        textureHeight = tileSet.Images[0].height;

                        reducedLayerInfo.TextureId = tilesetIndex;
                        toReturn.Layers.Add(reducedLayerInfo);
                    }


                    var objectGroup = tiledMapSave.MapLayers[layerIndex] as mapObjectgroup;

                    // This code only works based on the assumption that only one tileset will be used in any given object layer's image objects
                    var mapObjectgroupObject = [email protected](o => o.gid != null);

                    if (mapObjectgroupObject?.gid != null)
                    {
                        var idOfTexture = mapObjectgroupObject.gid.Value;
                        Tileset tileSet = tiledMapSave.GetTilesetForGid(idOfTexture);
                        var tilesetIndex = tiledMapSave.Tilesets.IndexOf(tileSet);

                        textureWidth = tileSet.Images[0].width;
                        textureHeight = tileSet.Images[0].height;
                        reducedLayerInfo.TextureId = tilesetIndex;
                        toReturn.Layers.Add(reducedLayerInfo);
                    }
                }

                ReducedQuadInfo quad = ReducedQuadInfo.FromSpriteSave(spriteSave, textureWidth, textureHeight);

                if (currentLayer is mapObjectgroup)
                {
                    var objectInstance = (currentLayer as mapObjectgroup).@object[indexInLayer];

                    if (objectInstance.properties.Count != 0)
                    {
                        var nameProperty = objectInstance.properties.FirstOrDefault(item => item.StrippedNameLower == "name");
                        if (nameProperty != null)
                        {
                            quad.Name = nameProperty.value;
                        }
                        else
                        {
                            quad.Name = spriteSave.Name;

                            bool needsName = string.IsNullOrEmpty(spriteSave.Name);
                            if (needsName)
                            {
                                quad.Name = $"_{currentLayer.Name}runtime{indexInLayer}";
                            }
                        }

                        List<NamedValue> list = new List<NamedValue>();

                        foreach (var property in objectInstance.properties)
                        {
                            list.Add(
                                new NamedValue
                                {
                                    Name = property.StrippedName,
                                    Value = property.value,
                                    Type = property.Type
                                }
                            );
                        }

                        quad.QuadSpecificProperties = list;
                    }
                }

                reducedLayerInfo?.Quads.Add(quad);

                indexInLayer++;
            }
            return toReturn;



        }
Esempio n. 3
0
        public SceneSave ToSceneSave(float scale, FileReferenceType referenceType = FileReferenceType.NoDirectory)
        {
            var toReturn = new SceneSave {
                CoordinateSystem = FlatRedBall.Math.CoordinateSystem.RightHanded
            };

            // TODO: Somehow add all layers separately

            int layercount = 0;

            foreach (MapLayer mapLayer in this.Layers)
            {
                if (!mapLayer.IsVisible)
                {
                    switch (mapLayer.VisibleBehavior)
                    {
                    case LayerVisibleBehavior.Ignore:
                        break;

                    case LayerVisibleBehavior.Skip:
                        continue;
                    }
                }

                MapLayer mLayer      = mapLayer;
                int      mLayerCount = layercount;

                for (int i = 0; i < mapLayer.data[0].tiles.Count; i++)
                //Parallel.For(0, mapLayer.data[0].tiles.Count, i =>
                {
                    uint    gid     = mLayer.data[0].tiles[i];
                    Tileset tileSet = GetTilesetForGid(gid);
                    if (tileSet != null)
                    {
                        SpriteSave sprite = CreateSpriteSaveFromMapTileset(scale, mLayerCount, mLayer, i, gid, tileSet, referenceType);
                        lock (toReturn)
                        {
                            toReturn.SpriteList.Add(sprite);
                        }
                    }
                }
                //);
                ++layercount;
            }
            if (this.objectgroup != null && this.objectgroup.Count != 0)
            {
                foreach (mapObjectgroup group in this.objectgroup)
                {
                    if (group.@object != null && !string.IsNullOrEmpty(group.name)) //&& (string.IsNullOrEmpty(layerName) || group.name.Equals(layerName)))
                    {
                        foreach (mapObjectgroupObject @object in group.@object)
                        {
                            if (!String.IsNullOrEmpty(@object.gid))
                            {
                                SpriteSave sprite = CreateSpriteSaveFromObject(scale, @object, layercount, referenceType);
                                lock (toReturn)
                                {
                                    toReturn.SpriteList.Add(sprite);
                                }
                            }
                        }
                    }
                }
            }
            return(toReturn);
        }
        private static void CreateFromTiledMapSave(TiledMapSave tiledMapSave, string directory, FileReferenceType referenceType,
                                                   ReducedTileMapInfo reducedTileMapInfo)
        {
            ReducedLayerInfo reducedLayerInfo = null;

            for (int i = 0; i < tiledMapSave.MapLayers.Count; i++)
            {
                var tiledLayer = tiledMapSave.MapLayers[i];

                string texture = null;

                uint    tileIdOfTexture = 0;
                Tileset tileSet         = null;
                uint?   firstGid        = null;

                if (tiledLayer is MapLayer)
                {
                    var mapLayer = tiledLayer as MapLayer;

                    if (mapLayer.data.Length != 0)
                    {
                        firstGid = mapLayer.data[0].tiles.FirstOrDefault(item => item != 0);
                    }
                }
                else
                {
                    var objectLayer = tiledLayer as mapObjectgroup;

                    var firstObjectWithTexture = [email protected](item => item.gid != 0);

                    firstGid = firstObjectWithTexture?.gid;
                }

                if (firstGid > 0)
                {
                    tileSet = tiledMapSave.GetTilesetForGid(firstGid.Value);
                    if (tileSet != null)
                    {
                        if (referenceType == FileReferenceType.NoDirectory)
                        {
                            texture = tileSet.Images[0].sourceFileName;
                        }
                        else if (referenceType == FileReferenceType.Absolute)
                        {
                            if (!string.IsNullOrEmpty(tileSet.SourceDirectory) && tileSet.SourceDirectory != ".")
                            {
                                directory += tileSet.SourceDirectory;

                                directory = FlatRedBall.IO.FileManager.RemoveDotDotSlash(directory);
                            }

                            texture = FlatRedBall.IO.FileManager.RemoveDotDotSlash(directory + tileSet.Images[0].Source);
                        }
                        else
                        {
                            throw new NotImplementedException();
                        }
                    }



                    int tileWidth  = FlatRedBall.Math.MathFunctions.RoundToInt(tiledMapSave.tilewidth);
                    int tileHeight = FlatRedBall.Math.MathFunctions.RoundToInt(tiledMapSave.tileheight);

                    reducedLayerInfo = new ReducedLayerInfo
                    {
                        Z          = i,
                        Texture    = texture,
                        Name       = tiledLayer.Name,
                        TileWidth  = tileWidth,
                        TileHeight = tileHeight,
                    };

                    reducedTileMapInfo.Layers.Add(reducedLayerInfo);

                    var tilesetIndex = tiledMapSave.Tilesets.IndexOf(tileSet);
                    reducedLayerInfo.TextureId = tilesetIndex;


                    // create the quad here:
                    if (tiledLayer is MapLayer)
                    {
                        AddTileLayerTiles(tiledMapSave, reducedLayerInfo, i, tiledLayer, tileSet, tileWidth, tileHeight);
                    }

                    else if (tiledLayer is mapObjectgroup)
                    {
                        AddObjectLayerTiles(reducedLayerInfo, tiledLayer, tileSet, firstGid, tileWidth, tileHeight);
                    }
                }
            }
        }
        /// <summary>
        /// Converts a TiledMapSave to a ReducedTileMapInfo object
        /// </summary>
        /// <param name="tiledMapSave">The TiledMapSave to convert</param>
        /// <param name="scale">The amount to scale by - default of 1</param>
        /// <param name="zOffset">The zOffset</param>
        /// <param name="directory">The directory of the file associated with the tiledMapSave, used to find file references.</param>
        /// <param name="referenceType">How the files in the .tmx are referenced.</param>
        /// <returns></returns>
        public static ReducedTileMapInfo FromTiledMapSave(TiledMapSave tiledMapSave, float scale, float zOffset, string directory, FileReferenceType referenceType)
        {
            var toReturn = new ReducedTileMapInfo
            {
                NumberCellsTall = tiledMapSave.Height,
                NumberCellsWide = tiledMapSave.Width
            };

            toReturn.CellHeightInPixels = (ushort)tiledMapSave.tileheight;
            toReturn.CellWidthInPixels  = (ushort)tiledMapSave.tilewidth;
            toReturn.QuadHeight         = tiledMapSave.tileheight;
            toReturn.QuadWidth          = tiledMapSave.tilewidth;


            if (FastCreateFromTmx)
            {
                CreateFromTiledMapSave(tiledMapSave, directory, referenceType, toReturn);
            }
            else
            {
                // slow:
                CreateFromSpriteEditorScene(tiledMapSave, scale, zOffset, referenceType, toReturn);
            }

            return(toReturn);
        }
        private static void CreateFromSpriteEditorScene(TiledMapSave tiledMapSave, float scale, float zOffset, FileReferenceType referenceType, ReducedTileMapInfo toReturn)
        {
            var ses = tiledMapSave.ToSceneSave(scale, referenceType);

            // This is not a stable sort!
            //ses.SpriteList.Sort((first, second) => first.Z.CompareTo(second.Z));
            ses.SpriteList = ses.SpriteList.OrderBy(item => item.Z).ToList();

            ReducedLayerInfo reducedLayerInfo = null;

            float z = float.NaN;


            int textureWidth  = 0;
            int textureHeight = 0;

            AbstractMapLayer currentLayer = null;
            int indexInLayer = 0;


            foreach (var spriteSave in ses.SpriteList)
            {
                if (spriteSave.Z != z)
                {
                    indexInLayer = 0;
                    z            = spriteSave.Z;


                    int layerIndex       = FlatRedBall.Math.MathFunctions.RoundToInt(z - zOffset);
                    var abstractMapLayer = tiledMapSave.MapLayers[layerIndex];
                    currentLayer = abstractMapLayer;

                    reducedLayerInfo = new ReducedLayerInfo
                    {
                        Z          = spriteSave.Z,
                        Texture    = spriteSave.Texture,
                        Name       = abstractMapLayer.Name,
                        TileWidth  = FlatRedBall.Math.MathFunctions.RoundToInt(spriteSave.ScaleX * 2),
                        TileHeight = FlatRedBall.Math.MathFunctions.RoundToInt(spriteSave.ScaleY * 2)
                    };

                    var mapLayer = abstractMapLayer as MapLayer;
                    // This should have data:
                    if (mapLayer != null)
                    {
                        var     idOfTexture  = mapLayer.data[0].tiles.FirstOrDefault(item => item != 0);
                        Tileset tileSet      = tiledMapSave.GetTilesetForGid(idOfTexture);
                        var     tilesetIndex = tiledMapSave.Tilesets.IndexOf(tileSet);

                        textureWidth  = tileSet.Images[0].width;
                        textureHeight = tileSet.Images[0].height;

                        reducedLayerInfo.TextureId = tilesetIndex;
                        toReturn.Layers.Add(reducedLayerInfo);
                    }


                    var objectGroup = tiledMapSave.MapLayers[layerIndex] as mapObjectgroup;

                    // This code only works based on the assumption that only one tileset will be used in any given object layer's image objects
                    var mapObjectgroupObject = [email protected](o => o.gid != null);

                    if (mapObjectgroupObject?.gid != null)
                    {
                        var     idOfTexture  = mapObjectgroupObject.gid.Value;
                        Tileset tileSet      = tiledMapSave.GetTilesetForGid(idOfTexture);
                        var     tilesetIndex = tiledMapSave.Tilesets.IndexOf(tileSet);

                        textureWidth  = tileSet.Images[0].width;
                        textureHeight = tileSet.Images[0].height;
                        reducedLayerInfo.TextureId = tilesetIndex;
                        toReturn.Layers.Add(reducedLayerInfo);
                    }
                }

                ReducedQuadInfo quad = ReducedQuadInfo.FromSpriteSave(spriteSave, textureWidth, textureHeight);

                if (currentLayer is mapObjectgroup)
                {
                    var asMapObjectGroup = currentLayer as mapObjectgroup;
                    var objectInstance   = asMapObjectGroup.@object[indexInLayer];

                    // skip over any non-sprite objects:
                    while (objectInstance.gid == null)
                    {
                        indexInLayer++;
                        if (indexInLayer >= [email protected])
                        {
                            objectInstance = null;
                            break;
                        }
                        else
                        {
                            objectInstance = asMapObjectGroup.@object[indexInLayer];
                        }
                    }

                    if (objectInstance != null && objectInstance.properties.Count != 0)
                    {
                        var nameProperty = objectInstance.properties.FirstOrDefault(item => item.StrippedNameLower == "name");
                        if (nameProperty != null)
                        {
                            quad.Name = nameProperty.value;
                        }
                        else
                        {
                            quad.Name = spriteSave.Name;

                            bool needsName = string.IsNullOrEmpty(spriteSave.Name);
                            if (needsName)
                            {
                                quad.Name = $"_{currentLayer.Name}runtime{indexInLayer}";
                            }
                        }

                        List <NamedValue> list = new List <NamedValue>();

                        foreach (var property in objectInstance.properties)
                        {
                            list.Add(
                                new NamedValue
                            {
                                Name  = property.StrippedName,
                                Value = property.value,
                                Type  = property.Type
                            }
                                );
                        }

                        quad.QuadSpecificProperties = list;
                    }
                }

                reducedLayerInfo?.Quads.Add(quad);

                indexInLayer++;
            }
        }
        /// <summary>
        /// Converts a TiledMapSave to a ReducedTileMapInfo object
        /// </summary>
        /// <param name="tiledMapSave">The TiledMapSave to convert</param>
        /// <param name="scale">The amount to scale by - default of 1</param>
        /// <param name="zOffset">The zOffset</param>
        /// <param name="directory">The directory of the file associated with the tiledMapSave, used to find file references.</param>
        /// <param name="referenceType">How the files in the .tmx are referenced.</param>
        /// <returns></returns>
        public static ReducedTileMapInfo FromTiledMapSave(TiledMapSave tiledMapSave, float scale, float zOffset, string directory, FileReferenceType referenceType)
        {
            var toReturn = new ReducedTileMapInfo();

            toReturn.NumberCellsTall = tiledMapSave.Height;
            toReturn.NumberCellsWide = tiledMapSave.Width;

            var ses = tiledMapSave.ToSceneSave(scale, referenceType);

            ses.SpriteList.Sort((first, second) => first.Z.CompareTo(second.Z));

            ReducedLayerInfo reducedLayerInfo = null;

            // If we rely on the image, it's both slow (have to open the images), and
            // doesn't work at runtime in games:
            //Dictionary<string, Point> loadedTextures = new Dictionary<string, Point>();
            //SetCellWidthAndHeight(tiledMapSave, directory, toReturn, ses, loadedTextures);

            toReturn.CellHeightInPixels = (ushort)tiledMapSave.tileheight;
            toReturn.CellWidthInPixels  = (ushort)tiledMapSave.tilewidth;


            SetQuadWidthAndHeight(toReturn, ses);

            float z = float.NaN;


            int textureWidth  = 0;
            int textureHeight = 0;


            for (int i = 0; i < ses.SpriteList.Count; i++)
            {
                SpriteSave spriteSave = ses.SpriteList[i];

                if (spriteSave.Z != z)
                {
                    z = spriteSave.Z;
                    reducedLayerInfo         = new ReducedLayerInfo();
                    reducedLayerInfo.Z       = spriteSave.Z;
                    reducedLayerInfo.Texture = spriteSave.Texture;

                    int layerIndex = FlatRedBall.Math.MathFunctions.RoundToInt(z - zOffset);
                    var mapLayer   = tiledMapSave.Layers[layerIndex];


                    // This should have data:

                    var     idOfTexture  = mapLayer.data[0].tiles.FirstOrDefault(item => item != 0);
                    Tileset tileSet      = tiledMapSave.GetTilesetForGid(idOfTexture);
                    var     tilesetIndex = tiledMapSave.Tilesets.IndexOf(tileSet);

                    textureWidth  = tileSet.Images[0].width;
                    textureHeight = tileSet.Images[0].height;

                    reducedLayerInfo.Name      = mapLayer.Name;
                    reducedLayerInfo.TextureId = tilesetIndex;
                    toReturn.Layers.Add(reducedLayerInfo);
                }

                ReducedQuadInfo quad = ReducedQuadInfo.FromSpriteSave(spriteSave, textureWidth, textureHeight);
                reducedLayerInfo.Quads.Add(quad);
            }
            return(toReturn);
        }