internal MapObjectLayer(string name, int width, int height, bool visible, float opacity, PropertyCollection properties, IList <MapObject> objects) : base(name, width, height, visible, opacity, properties) { Objects = new ReadOnlyCollection <MapObject>(objects); foreach (var o in objects) { string oname = o.Name; if (namedObjects.ContainsKey(o.Name)) { oname += "-" + Guid.NewGuid(); } namedObjects.Add(oname, o); } }
public MapContent(XmlDocument document, ContentImporterContext context) { XmlNode mapNode = document["map"]; Version = mapNode.Attributes["version"].Value; Orientation = (Orientation)Enum.Parse(typeof(Orientation), mapNode.Attributes["orientation"].Value, true); Width = int.Parse(mapNode.Attributes["width"].Value, CultureInfo.InvariantCulture); Height = int.Parse(mapNode.Attributes["height"].Value, CultureInfo.InvariantCulture); TileWidth = int.Parse(mapNode.Attributes["tilewidth"].Value, CultureInfo.InvariantCulture); TileHeight = int.Parse(mapNode.Attributes["tileheight"].Value, CultureInfo.InvariantCulture); XmlNode propertiesNode = document.SelectSingleNode("map/properties"); if (propertiesNode != null) { Properties = new PropertyCollection(propertiesNode, context); } foreach (XmlNode tileSet in document.SelectNodes("map/tileset")) { if (tileSet.Attributes["source"] != null) { TileSets.Add(new ExternalTileSetContent(tileSet, context)); } else { TileSets.Add(new TileSetContent(tileSet, context)); } } foreach (XmlNode layerNode in document.SelectNodes("map/layer|map/objectgroup")) { LayerContent layerContent; if (layerNode.Name == "layer") { layerContent = new TileLayerContent(layerNode, context); } else if (layerNode.Name == "objectgroup") { layerContent = new MapObjectLayerContent(layerNode, context); } else { throw new Exception("Unknown layer name: " + layerNode.Name); } // Layer names need to be unique for our lookup system, but Tiled // doesn't require unique names. string layerName = layerContent.Name; int duplicateCount = 2; // if a layer already has the same name... if (Layers.Find(l => l.Name == layerName) != null) { // figure out a layer name that does work do { layerName = string.Format("{0}{1}", layerContent.Name, duplicateCount); duplicateCount++; } while (Layers.Find(l => l.Name == layerName) != null); // log a warning for the user to see context.Logger.LogWarning(string.Empty, new ContentIdentity(), "Renaming layer \"{1}\" to \"{2}\" to make a unique name.", layerContent.Type, layerContent.Name, layerName); // save that name layerContent.Name = layerName; } Layers.Add(layerContent); } }
internal TileLayer(string name, int width, int height, float layerDepth, bool visible, float opacity, PropertyCollection properties, Map map, uint[] data, bool makeUnique) : base(name, width, height, layerDepth, visible, opacity, properties) { Tiles = new TileGrid(width, height); // data is left-to-right, top-to-bottom for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { uint index = data[y * width + x]; // compute the SpriteEffects to apply to this tile SpriteEffects spriteEffects = SpriteEffects.None; if ((index & FlippedHorizontallyFlag) != 0) { spriteEffects |= SpriteEffects.FlipHorizontally; } if ((index & FlippedVerticallyFlag) != 0) { spriteEffects |= SpriteEffects.FlipVertically; } // strip out the flip flags to get the real ID int id = (int)(index & ~(FlippedVerticallyFlag | FlippedHorizontallyFlag)); // get the tile Tile t = map.Tiles[id]; // if the tile is non-null... if (t != null) { // if we want unique instances, clone it if (makeUnique) { t = t.Clone(); t.SpriteEffects = spriteEffects; } // otherwise we may need to clone if the tile doesn't have the correct effects // in this world a flipped tile is different than a non-flipped one; just because // they have the same source rect doesn't mean they're equal. else if (t.SpriteEffects != spriteEffects) { t = t.Clone(); t.SpriteEffects = spriteEffects; } } // put that tile in our grid Tiles[x, y] = t; } } }
internal MapObjectLayer(string name, int width, int height, float layerDepth, bool visible, float opacity, PropertyCollection properties, List <MapObject> initialObjects) : base(name, width, height, layerDepth, visible, opacity, properties) { Objects = new ReadOnlyCollection <MapObject>(objects); initialObjects.ForEach(AddObject); }
public MapObjectContent(XmlNode node, ContentImporterContext context) { // get the object's name and type if (node.Attributes["name"] != null) { Name = node.Attributes["name"].Value; } if (node.Attributes["type"] != null) { Type = node.Attributes["type"].Value; } // read the object properties if (node["properties"] != null) { Properties = new PropertyCollection(node["properties"], context); } // parse out the bounds of the object. values default to 0 if the attribute is missing from the node. int x = node.Attributes["x"] != null?int.Parse(node.Attributes["x"].Value, CultureInfo.InvariantCulture) : 0; int y = node.Attributes["y"] != null?int.Parse(node.Attributes["y"].Value, CultureInfo.InvariantCulture) : 0; int width = node.Attributes["width"] != null?int.Parse(node.Attributes["width"].Value, CultureInfo.InvariantCulture) : 0; int height = node.Attributes["height"] != null?int.Parse(node.Attributes["height"].Value, CultureInfo.InvariantCulture) : 0; Bounds = new Rectangle(x, y, width, height); // stores a string of points to parse out if this object is a polygon or polyline string pointsAsString = null; // if there's a GID, it's a tile object if (node.Attributes["gid"] != null) { ObjectType = MapObjectType.Tile; GID = int.Parse(node.Attributes["gid"].Value, CultureInfo.InvariantCulture); } // if there's a polygon node, it's a polygon object else if (node["polygon"] != null) { ObjectType = MapObjectType.Polygon; pointsAsString = node["polygon"].Attributes["points"].Value; } // if there's a polyline node, it's a polyline object else if (node["polyline"] != null) { ObjectType = MapObjectType.Polyline; pointsAsString = node["polyline"].Attributes["points"].Value; } // if we have some points to parse, we do that now if (pointsAsString != null) { // points are separated first by spaces string[] pointPairs = pointsAsString.Split(' '); foreach (string p in pointPairs) { // then we split on commas string[] coords = p.Split(','); // then we parse the X/Y coordinates Points.Add(new Vector2( float.Parse(coords[0], CultureInfo.InvariantCulture), float.Parse(coords[1], CultureInfo.InvariantCulture))); } } }
//private Layer collisionLayer; internal Map(ContentReader reader) { // read in the basic map information Version = new Version(reader.ReadString()); Orientation = (Orientation)reader.ReadByte(); Width = reader.ReadInt32(); Height = reader.ReadInt32(); TileWidth = reader.ReadInt32(); TileHeight = reader.ReadInt32(); Properties = new PropertyCollection(); Properties.Read(reader); // create a list for our tiles List <Tile> tiles = new List <Tile>(); Tiles = new Collection <Tile>(tiles); // read in each tile set int numTileSets = reader.ReadInt32(); for (int i = 0; i < numTileSets; i++) { // get the id and texture int firstId = reader.ReadInt32(); string tilesetName = reader.ReadString(); bool collisionSet = reader.ReadBoolean(); Texture2D texture = reader.ReadExternalReference <Texture2D>(); Texture2D whiteTexture = null;// reader.ReadExternalReference<Texture2D>(); // Read in color data for collision purposes // You'll probably want to limit this to just the tilesets that are used for collision // I'm checking for the name of my tileset that contains wall tiles // Color data takes up a fair bit of RAM Color[] collisionData = null; bool[] collisionBitData = null; if (collisionSet) { collisionData = new Color[texture.Width * texture.Height]; collisionBitData = new bool[texture.Width * texture.Height]; texture.GetData <Color>(collisionData); for (int col = 0; col < collisionData.Length; col++) { if (collisionData[col].A > 0) { collisionBitData[col] = true; } } collisionData = null; } // read in each individual tile int numTiles = reader.ReadInt32(); for (int j = 0; j < numTiles; j++) { int id = firstId + j; Rectangle source = reader.ReadObject <Rectangle>(); PropertyCollection props = new PropertyCollection(); props.Read(reader); Tile t = new Tile(texture, whiteTexture, source, props, collisionBitData); while (id >= tiles.Count) { tiles.Add(null); } tiles.Insert(id, t); } } // read in all the layers List <Layer> layers = new List <Layer>(); Layers = new ReadOnlyCollection <Layer>(layers); int numLayers = reader.ReadInt32(); for (int i = 0; i < numLayers; i++) { Layer layer = null; // read generic layer data string type = reader.ReadString(); string name = reader.ReadString(); int width = reader.ReadInt32(); int height = reader.ReadInt32(); bool visible = reader.ReadBoolean(); float opacity = reader.ReadSingle(); PropertyCollection props = new PropertyCollection(); props.Read(reader); // using the type, figure out which object to create if (type == "layer") { int[] data = reader.ReadObject <int[]>(); layer = new TileLayer(name, width, height, visible, opacity, props, this, data); } else if (type == "objectgroup") { List <MapObject> objects = new List <MapObject>(); // read in all of our objects int numObjects = reader.ReadInt32(); for (int j = 0; j < numObjects; j++) { string objName = reader.ReadString(); string objType = reader.ReadString(); Rectangle objLoc = reader.ReadObject <Rectangle>(); List <Point> objPoints = reader.ReadObject <List <Point> >(); PropertyCollection objProps = new PropertyCollection(); objProps.Read(reader); objects.Add(new MapObject(objName, objType, objLoc, objPoints, objProps)); } layer = new MapObjectLayer(name, width, height, visible, opacity, props, objects); } else { throw new Exception("Invalid type: " + type); } layers.Add(layer); namedLayers.Add(name, layer); } }