public static ShapeCollectionSave ToShapeCollectionSave(this TiledMapSave tiledMapSave, string layerName) { MapLayer mapLayer = null; if (!string.IsNullOrEmpty(layerName)) { mapLayer = tiledMapSave.Layers.FirstOrDefault(l => l.Name.Equals(layerName)); } var shapes = new ShapeCollectionSave(); if ((mapLayer != null && !mapLayer.IsVisible && mapLayer.VisibleBehavior == TMXGlueLib.TiledMapSave.LayerVisibleBehavior.Skip) || tiledMapSave.objectgroup == null || tiledMapSave.objectgroup.Count == 0) { return(shapes); } foreach (mapObjectgroup group in tiledMapSave.objectgroup) { if (group.@object != null && !string.IsNullOrEmpty(group.Name) && (string.IsNullOrEmpty(layerName) || group.Name.Equals(layerName))) { foreach (mapObjectgroupObject @object in group.@object) { ///November 8th, 2015 ///Jesse Crafts-Finch ///If a polygon has a gid, and therefore an image associate with it, it will be turned into a spritesave, not a polygon. if (@object.gid != null) { continue; } if (@object.polygon != null) { foreach (mapObjectgroupObjectPolygon polygon in @object.polygon) { // TODO: Make this a rectangle object PolygonSave p = tiledMapSave.ConvertTmxObjectToFrbPolygonSave(@object.Name, @object.x, @object.y, @object.Rotation, polygon.points, true); if (p != null) { shapes.PolygonSaves.Add(p); } } } if (@object.polyline != null) { foreach (mapObjectgroupObjectPolyline polyline in @object.polyline) { PolygonSave p = tiledMapSave.ConvertTmxObjectToFrbPolygonSave(@object.Name, @object.x, @object.y, @object.Rotation, polyline.points, false); if (p != null) { shapes.PolygonSaves.Add(p); } } } if (@object.polygon == null && @object.polyline == null) { PolygonSave p = tiledMapSave.ConvertTmxObjectToFrbPolygonSave(@object.Name, @object.x, @object.y, @object.width, @object.height, @object.Rotation, @object.ellipse); if (p != null) { shapes.PolygonSaves.Add(p); } } } } } return(shapes); }
private static void AddTileShapeCollectionForLayer(TMXGlueLib.MapLayer layer, Dictionary <string, TileCollisions.TileShapeCollection> collisionDictionary, TMXGlueLib.Tileset tileset, float tileDimension, float z, bool separateOnTileType) { Math.Geometry.AxisAlignedRectangle rectangle = null; Math.Geometry.Polygon polygon = null; Circle circle; var tiles = layer.data[0].tiles; bool sortOnY = layer.height > layer.width; if (tileset != null) { foreach (var tilesetTile in tileset.Tiles.Where(item => item.Objects?.@object?.Length > 0)) { var tilesetTileGid = tilesetTile.id + tileset.Firstgid; foreach (var tilesetObject in tilesetTile.Objects.@object) { var name = layer.Name; TiledMapToShapeCollectionConverter.ConvertTiledObjectToFrbShape(tilesetObject, out polygon, out rectangle, out circle); if (rectangle != null) { var collectionName = layer.Name; if (tilesetObject.Type != null && separateOnTileType) { collectionName += "_" + tilesetObject.Type; } var collection = GetOrAddTileShapeCollection(collectionName, collisionDictionary); collection.GridSize = tileDimension; rectangle.Z = z; if (sortOnY) { for (int y = 0; y < layer.height; y++) { for (int x = 0; x < layer.width; x++) { AddRectangleCloneAtXY(layer, tileDimension, rectangle, tiles, tilesetTileGid, x, y, collection); } } } else { for (int x = 0; x < layer.width; x++) { for (int y = 0; y < layer.height; y++) { AddRectangleCloneAtXY(layer, tileDimension, rectangle, tiles, tilesetTileGid, x, y, collection); } } } } else if (polygon != null) { var collectionName = layer.Name; if (tilesetObject.Type != null && separateOnTileType) { collectionName += "_" + tilesetObject.Type; } var collection = GetOrAddTileShapeCollection(collectionName, collisionDictionary); collection.GridSize = tileDimension; // For tile polygons we want them to be centered on the tile. // To do this, we shift all points by its position: for (int i = 0; i < polygon.Points.Count; i++) { var point = polygon.Points[i]; point.X += polygon.Position.X - tileDimension / 2.0f; point.Y += polygon.Position.Y + tileDimension / 2.0f; polygon.SetPoint(i, point); } polygon.Z = z; if (sortOnY) { for (int y = 0; y < layer.height; y++) { for (int x = 0; x < layer.width; x++) { var i = y * layer.width + x; if ((tiles[i] & 0x0fffffff) == tilesetTileGid) { var cloned = AddPolygonCloneAtXY(layer, tileDimension, polygon, tiles, tilesetTileGid, i, collection); ApplyFlip(tiles[i], cloned); } } } } else { for (int x = 0; x < layer.width; x++) { for (int y = 0; y < layer.height; y++) { var i = y * layer.width + x; if ((tiles[i] & 0x0fffffff) == tilesetTileGid) { var cloned = AddPolygonCloneAtXY(layer, tileDimension, polygon, tiles, tilesetTileGid, i, collection); ApplyFlip(tiles[i], cloned); } } } } } else if (circle != null) { throw new NotImplementedException("Need to handle circles..."); } } } } }
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); }
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); }
public NodeNetwork ToNodeNetwork(bool linkHorizontally, bool linkVertically, bool linkDiagonally, bool requireTile) { var toReturn = new NodeNetwork(); int layercount = 0; foreach (MapLayer mapLayer in this.Layers) { if (!mapLayer.IsVisible) { switch (mapLayer.VisibleBehavior) { case LayerVisibleBehavior.Ignore: break; case LayerVisibleBehavior.Skip: continue; } } var allNodes = new Dictionary <int, Dictionary <int, Dictionary <int, PositionedNode> > >(); allNodes[layercount] = new Dictionary <int, Dictionary <int, PositionedNode> >(); MapLayer mLayer = mapLayer; int mLayerCount = layercount; Parallel.For(0, mapLayer.data[0].tiles.Count, count => { uint gid = mLayer.data[0].tiles[count]; Tileset tileSet = GetTilesetForGid(gid); if (tileSet != null || !requireTile) { var node = new PositionedNode(); //int tileWidth = requireTile ? tileSet.tilewidth : tilewidth; //int tileHeight = requireTile ? tileSet.tileheight : tileheight; int x = count % this.Width; int y = count / this.Width; float nodex; float nodey; float nodez; CalculateWorldCoordinates(mLayerCount, count, tilewidth, tileheight, mLayer.width, out nodex, out nodey, out nodez); node.X = nodex; node.Y = nodey; node.Z = nodez; lock (allNodes) { if (!allNodes[mLayerCount].ContainsKey(x)) { allNodes[mLayerCount][x] = new Dictionary <int, PositionedNode>(); } allNodes[mLayerCount][x][y] = node; } node.Name = string.Format("Node {0}", count); lock (toReturn) { toReturn.AddNode(node); } } }); SetupNodeLinks(linkHorizontally, linkVertically, linkDiagonally, allNodes[layercount]); RemoveExcludedNodesViaPolygonLayer(toReturn, mapLayer, allNodes[layercount]); LowerNodesInNodesDownShapeCollection(mapLayer, allNodes[layercount]); RaiseNodesInNodesUpShapeCollection(mapLayer, allNodes[layercount]); ++layercount; } toReturn.UpdateShapes(); return(toReturn); }
private static TileCollisions.TileShapeCollection GetTileShapeCollectionForLayer(TMXGlueLib.MapLayer layer, TMXGlueLib.Tileset tileset, float tileDimension, float z) { TileCollisions.TileShapeCollection toReturn = new TileCollisions.TileShapeCollection(); toReturn.Name = layer.Name; Math.Geometry.AxisAlignedRectangle rectangle = null; Math.Geometry.Polygon polygon = null; Circle circle; var tiles = layer.data[0].tiles; bool sortOnY = layer.height > layer.width; foreach (var tilesetTile in tileset.Tiles.Where(item => item.Objects?.@object?.Length > 0)) { var tilesetTileGid = tilesetTile.id + tileset.Firstgid; foreach (var tilesetObject in tilesetTile.Objects.@object) { TiledMapToShapeCollectionConverter.ConvertTiledObjectToFrbShape(tilesetObject, out polygon, out rectangle, out circle); if (rectangle != null) { rectangle.Z = z; if (sortOnY) { for (int y = 0; y < layer.height; y++) { for (int x = 0; x < layer.width; x++) { AddRectangleCloneAtXY(layer, tileDimension, toReturn, rectangle, tiles, tilesetTileGid, x, y); } } } else { for (int x = 0; x < layer.width; x++) { for (int y = 0; y < layer.height; y++) { AddRectangleCloneAtXY(layer, tileDimension, toReturn, rectangle, tiles, tilesetTileGid, x, y); } } } } else if (polygon != null) { // For tile polygons we want them to be centered on the tile. // To do this, we shift all points by its position: for (int i = 0; i < polygon.Points.Count; i++) { var point = polygon.Points[i]; point.X += polygon.Position.X - tileDimension / 2.0f; point.Y += polygon.Position.Y + tileDimension / 2.0f; polygon.SetPoint(i, point); } polygon.Z = z; if (sortOnY) { for (int y = 0; y < layer.height; y++) { for (int x = 0; x < layer.width; x++) { AddPolygonCloneAtXY(layer, tileDimension, toReturn, polygon, tiles, tilesetTileGid, x, y); } } } else { for (int x = 0; x < layer.width; x++) { for (int y = 0; y < layer.height; y++) { AddPolygonCloneAtXY(layer, tileDimension, toReturn, polygon, tiles, tilesetTileGid, x, y); } } } } else if (circle != null) { throw new NotImplementedException("Need to handle circles..."); } } } // The values are inserted sorted above for speed, now we set the XAxis - this will also sort but will be fast: if (sortOnY) { toReturn.SortAxis = Math.Axis.Y; } else { toReturn.SortAxis = Math.Axis.X; } toReturn.RefreshAllRepositionDirections(); return(toReturn); }