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; }
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); }