/// <summary> /// Initialize the Window /// </summary> /// <param name="objectLayerNode">NanoXMLNode of the MapObjectLayer from with MapObject will be read</param> public static void Init(NanoXMLNode objectLayerNode) { // Get existing open window or if none, make a new one: TiledMapObjectsWindow window = (TiledMapObjectsWindow)EditorWindow.GetWindow(typeof(TiledMapObjectsWindow)); _objectLayerNode = objectLayerNode; string name = objectLayerNode.GetAttribute("name") != null? objectLayerNode.GetAttribute("name").Value: "ObjectLayer"; window.title = name; window.RebuildObjectsProperties(); }
/// <summary> /// Creates a Tile Layer from node /// </summary> /// <param name="node">XML node to parse</param> /// <param name="map">TileLayer parent Map</param> /// <param name="layerDepth">This Layer's zDepth</param> /// <param name="makeUnique">true to generate Unique Tiles</param> /// <param name="materials">List of Materials containing the TileSet textures</param> public TileLayer(NanoXMLNode node, Map map, int layerDepth, bool makeUnique, List <Material> materials) : base(node) { NanoXMLNode dataNode = node["data"]; Data = new uint[Width * Height]; LayerDepth = layerDepth; MakeUniqueTiles = makeUnique; // figure out what encoding is being used, if any, and process // the data appropriately if (dataNode.GetAttribute("encoding") != null) { string encoding = dataNode.GetAttribute("encoding").Value; if (encoding == "base64") { ReadAsBase64(dataNode); } else if (encoding == "csv") { ReadAsCsv(dataNode); } else { throw new Exception("Unknown encoding: " + encoding); } } else { // XML format simply lays out a lot of <tile gid="X" /> nodes inside of data. int i = 0; foreach (NanoXMLNode tileNode in dataNode.SubNodes) { if (tileNode.Name.Equals("tile")) { Data[i] = uint.Parse(tileNode.GetAttribute("gid").Value, CultureInfo.InvariantCulture); i++; } } if (i != Data.Length) { throw new Exception("Not enough tile nodes to fill data"); } } Initialize(map, Data, materials); }
protected Layer(NanoXMLNode node) { //string Type = node.Name; Name = node.GetAttribute("name").Value; if (string.IsNullOrEmpty(Name)) { Name = "Layer"; } if (node.GetAttribute("width") != null) { Width = int.Parse(node.GetAttribute("width").Value, CultureInfo.InvariantCulture); } else { Width = 0; } if (node.GetAttribute("height") != null) { Height = int.Parse(node.GetAttribute("height").Value, CultureInfo.InvariantCulture); } else { Height = 0; } if (node.GetAttribute("opacity") != null) { Opacity = float.Parse(node.GetAttribute("opacity").Value, CultureInfo.InvariantCulture); } else { Opacity = 1; } if (node.GetAttribute("visible") != null) { Visible = int.Parse(node.GetAttribute("visible").Value, CultureInfo.InvariantCulture) == 1; } else { Visible = true; } NanoXMLNode propertiesNode = node["properties"]; if (propertiesNode != null) { Properties = new PropertyCollection(propertiesNode); } LayerGameObject = new GameObject(Name); }
/// <summary> /// Creates a MapObject from node /// </summary> /// <param name="node">NanoXMLNode XML to parse</param> /// <param name="parentObjectLayer">This MapObject's MapObjectLayer parent</param> public MapObject(NanoXMLNode node, MapObjectLayer parentObjectLayer) : base(node) { if (node.GetAttribute("name") != null) { Name = node.GetAttribute("name").Value; } else { Name = "Object"; } if (node.GetAttribute("type") != null) { Type = node.GetAttribute("type").Value; } else { Type = string.Empty; } if (node.GetAttribute("visible") != null) { Visible = int.Parse(node.GetAttribute("visible").Value, CultureInfo.InvariantCulture) == 1; } else { Visible = true; } if (node.GetAttribute("gid") != null) { GID = int.Parse(node.GetAttribute("gid").Value, CultureInfo.InvariantCulture); } else { GID = 0; } ParentObjectLayer = parentObjectLayer; NanoXMLNode propertiesNode = node["properties"]; if (propertiesNode != null) { Properties = new PropertyCollection(propertiesNode); } }
private void ReadAsBase64(NanoXMLNode dataNode) { // get a stream to the decoded Base64 text Stream data = new MemoryStream(Convert.FromBase64String(dataNode.Value), false); // figure out what, if any, compression we're using. the compression determines // if we need to wrap our data stream in a decompression stream if (dataNode.GetAttribute("compression") != null) { string compression = dataNode.GetAttribute("compression").Value; if (compression == "gzip") { data = new Ionic.Zlib.GZipStream(data, Ionic.Zlib.CompressionMode.Decompress, false); } else if (compression == "zlib") { data = new Ionic.Zlib.ZlibStream(data, Ionic.Zlib.CompressionMode.Decompress, false); } else { throw new InvalidOperationException("Unknown compression: " + compression); } } // simply read in all the integers using (data) { using (BinaryReader reader = new BinaryReader(data)) { for (int i = 0; i < Data.Length; i++) { Data[i] = reader.ReadUInt32(); } } } }
/// <summary> /// c = command, c_CmdXmlParser /// </summary> public static void c_CmdXmlParser(string txt, short startIndex = 0, int count = 4) { txt = txt.Remove(startIndex, count); string strData = Encoding.UTF8.GetString(File.ReadAllBytes(txt)); NanoXMLDocument xml = new NanoXMLDocument(strData); NanoXMLNode myAttribute = xml.RootNode["text"]; if (myAttribute == null) { Console.WriteLine("[Error] myAttribute null"); } Console.WriteLine(myAttribute.Name); Console.WriteLine(myAttribute.Value); Console.WriteLine(myAttribute.GetAttribute("size").Value); }
/// <summary> /// Creates an Image Layer from node /// </summary> /// <param name="node">XML node to parse</param> /// <param name="map">ImageLayer parent Map</param> /// <param name="mapPath">Map's directory path</param> /// <param name="baseMaterial">Material to use on this SpriteRenderer</param> public ImageLayer(NanoXMLNode node, Map map, string mapPath, Material baseMaterial) : base(node) { NanoXMLNode imageNode = node["image"]; this.Image = imageNode.GetAttribute("source").Value; if (node.GetAttribute("x") != null) { Position.x = float.Parse(node.GetAttribute("x").Value, NumberStyles.Float) / (float)map.TileWidth; } if (node.GetAttribute("y") != null) { Position.y = -float.Parse(node.GetAttribute("y").Value, NumberStyles.Float) / (float)map.TileHeight; } // if the image is in any director up from us, just take the filename //if (this.Image.StartsWith("..")) // this.Image = Path.GetFileName(this.Image); if (imageNode.GetAttribute("trans") != null) { string color = imageNode.GetAttribute("trans").Value; string r = color.Substring(0, 2); string g = color.Substring(2, 2); string b = color.Substring(4, 2); this.ColorKey = new Color((byte)Convert.ToInt32(r, 16), (byte)Convert.ToInt32(g, 16), (byte)Convert.ToInt32(b, 16)); } SortingOrder = map.DefaultSortingOrder - LayerDepth; Parent = map.MapObject.transform; TileWidth = map.TileWidth; string texturePath = mapPath; if (!map.UsingStreamingAssetsPath) { // Parse the path if (Image.StartsWith("../")) { string path = Image; string rootPath = Directory.GetParent(mapPath).FullName; string appPath = Path.GetFullPath(Application.dataPath.Replace("/Assets", "")); while (path.StartsWith("../")) { rootPath = Directory.GetParent(rootPath).FullName; path = path.Remove(0, 3); } rootPath = rootPath.Replace(appPath, ""); path = Path.GetDirectoryName(path) + Path.AltDirectorySeparatorChar + Path.GetFileNameWithoutExtension(path); if (path.StartsWith("/")) { path = path.Remove(0, 1); } rootPath = rootPath.Replace(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); if (rootPath.Length > 0) { rootPath += Path.AltDirectorySeparatorChar; } texturePath = rootPath + path; } else { if (Path.GetDirectoryName(this.Image).Length > 0) { texturePath += Path.GetDirectoryName(this.Image) + Path.AltDirectorySeparatorChar; } texturePath += Path.GetFileNameWithoutExtension(this.Image); } this.Texture = Resources.Load <Texture2D>(texturePath); BuildGameObject(); } else { if (!texturePath.Contains("://")) { texturePath = "file://" + texturePath + Path.GetFileName(this.Image); } // Run Coroutine for WWW using TaskManager. new X_UniTMX.Utils.Task(LoadImageTexture(texturePath), true); } }
/// <summary> /// Load this TileSet's information from node /// </summary> /// <param name="node">NanoXMLNode to parse</param> /// <param name="map">Reference to the Map this TileSet is in</param> /// <param name="firstGID">First ID is a per-Map property, so External TileSets won't have this info in the node</param> protected TileSet(NanoXMLNode node, Map map, int firstGID = 1) { if (node.GetAttribute("firstgid") == null || !int.TryParse(node.GetAttribute("firstgid").Value, out FirstId)) { FirstId = firstGID; } //this.FirstId = int.Parse(node.GetAttribute("firstgid").Value, CultureInfo.InvariantCulture); this.Name = node.GetAttribute("name").Value; this.TileWidth = int.Parse(node.GetAttribute("tilewidth").Value, CultureInfo.InvariantCulture); this.TileHeight = int.Parse(node.GetAttribute("tileheight").Value, CultureInfo.InvariantCulture); if (node.GetAttribute("spacing") != null) { this.Spacing = int.Parse(node.GetAttribute("spacing").Value, CultureInfo.InvariantCulture); } if (node.GetAttribute("margin") != null) { this.Margin = int.Parse(node.GetAttribute("margin").Value, CultureInfo.InvariantCulture); } NanoXMLNode tileOffset = node["tileoffset"]; if (tileOffset != null) { this.TileOffsetX = int.Parse(tileOffset.GetAttribute("x").Value, CultureInfo.InvariantCulture); this.TileOffsetY = -int.Parse(tileOffset.GetAttribute("y").Value, CultureInfo.InvariantCulture); } NanoXMLNode imageNode = node["image"]; this.Image = imageNode.GetAttribute("source").Value; // if the image is in any director up from us, just take the filename //if (this.Image.StartsWith("..")) // this.Image = Path.GetFileName(this.Image); if (imageNode.GetAttribute("trans") != null) { string color = imageNode.GetAttribute("trans").Value; string r = color.Substring(0, 2); string g = color.Substring(2, 2); string b = color.Substring(4, 2); this.ColorKey = new Color((byte)Convert.ToInt32(r, 16), (byte)Convert.ToInt32(g, 16), (byte)Convert.ToInt32(b, 16)); } foreach (NanoXMLNode subNode in node.SubNodes) { if (subNode.Name.Equals("tile")) { int id = this.FirstId + int.Parse(subNode.GetAttribute("id").Value, CultureInfo.InvariantCulture); // Load Tile Properties, if any NanoXMLNode propertiesNode = subNode["properties"]; if (propertiesNode != null) { PropertyCollection properties = new PropertyCollection(propertiesNode); //Property.ReadProperties(propertiesNode); this.TileProperties.Add(id, properties); } // Load Tile Animation, if any NanoXMLNode animationNode = subNode["animation"]; if (animationNode != null) { TileAnimation _tileAnimation = new TileAnimation(); foreach (NanoXMLNode frame in animationNode.SubNodes) { if (!frame.Name.Equals("frame")) { continue; } int tileid = int.Parse(frame.GetAttribute("tileid").Value, CultureInfo.InvariantCulture) + FirstId; int duration = int.Parse(frame.GetAttribute("duration").Value, CultureInfo.InvariantCulture); _tileAnimation.AddTileFrame(tileid, duration); } this.AnimatedTiles.Add(id, _tileAnimation); } // Load Tile Objects, if any NanoXMLNode objectsNode = subNode["objectgroup"]; if (objectsNode != null) { List <TileObject> tileObjects = new List <TileObject>(); foreach (NanoXMLNode tileObjNode in objectsNode.SubNodes) { TileObject tObj = new TileObject(tileObjNode); tObj.ScaleObject(map.TileWidth, map.TileHeight, map.Orientation); tileObjects.Add(tObj); } // There's a bug in Tiled 0.10.1- where the objectgroup node won't go away even if you delete all objects from a tile's collision group. if (tileObjects.Count > 0) { TilesObjects.Add(id, tileObjects); } } } } }
/// <summary> /// Only derived classes should use this constructor. Creates an Object from a XML node /// </summary> /// <param name="node">XML node to parse</param> protected Object(NanoXMLNode node) { if (node.GetAttribute("rotation") != null) { Rotation = 360 - float.Parse(node.GetAttribute("rotation").Value, CultureInfo.InvariantCulture); } else { Rotation = 0; } // values default to 0 if the attribute is missing from the node float x = node.GetAttribute("x") != null?float.Parse(node.GetAttribute("x").Value, CultureInfo.InvariantCulture) : 0; float y = node.GetAttribute("y") != null?float.Parse(node.GetAttribute("y").Value, CultureInfo.InvariantCulture) : 0; float width = node.GetAttribute("width") != null?float.Parse(node.GetAttribute("width").Value, CultureInfo.InvariantCulture) : 1; float height = node.GetAttribute("height") != null?float.Parse(node.GetAttribute("height").Value, CultureInfo.InvariantCulture) : 1; Bounds = new Rect(x, y, width, height); this.ObjectType = ObjectType.Box; // stores a string of points to parse out if this object is a polygon or polyline string pointsAsString = null; if (node["ellipse"] != null) { ObjectType = ObjectType.Ellipse; } // if there's a polygon node, it's a polygon object else if (node["polygon"] != null) { pointsAsString = node["polygon"].GetAttribute("points").Value; ObjectType = ObjectType.Polygon; } // if there's a polyline node, it's a polyline object else if (node["polyline"] != null) { pointsAsString = node["polyline"].GetAttribute("points").Value; ObjectType = ObjectType.Polyline; } // if we have some points to parse, we do that now if (pointsAsString != null) { // points are separated first by spaces Points = new List <Vector2>(); 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))); } } }
/// <summary> /// Creates a Map Object Layer from node /// </summary> /// <param name="node">XML node to parse</param> /// <param name="tiledMap">MapObjectLayer parent Map</param> /// <param name="layerDepth">This Layer's zDepth</param> /// <param name="materials">List of Materials containing the TileSet textures</param> public MapObjectLayer(NanoXMLNode node, Map tiledMap, int layerDepth, List <Material> materials) : base(node) { if (node.GetAttribute("color") != null) { // get the color string, removing the leading # string color = node.GetAttribute("color").Value.Substring(1); // get the RGB individually string r = color.Substring(0, 2); string g = color.Substring(2, 2); string b = color.Substring(4, 2); // convert to the color Color = new Color( (byte)int.Parse(r, NumberStyles.AllowHexSpecifier), (byte)int.Parse(g, NumberStyles.AllowHexSpecifier), (byte)int.Parse(b, NumberStyles.AllowHexSpecifier)); } LayerGameObject.transform.parent = tiledMap.MapObject.transform; LayerGameObject.transform.localPosition = new Vector3(0, 0, this.LayerDepth); LayerGameObject.isStatic = true; LayerGameObject.SetActive(Visible); Objects = new List <MapObject>(); foreach (NanoXMLNode objectNode in node.SubNodes) { if (!objectNode.Name.Equals("object")) { continue; } MapObject mapObjectContent = new MapObject(objectNode, this); mapObjectContent.ScaleObject(tiledMap.TileWidth, tiledMap.TileHeight, tiledMap.Orientation); mapObjectContent.Name = this.Name + "_" + mapObjectContent.Name; // Object names need to be unique for our lookup system, but Tiled // doesn't require unique names. string objectName = mapObjectContent.Name; int duplicateCount = 2; // if a object already has the same name... if (Objects.Find(o => o.Name.Equals(objectName)) != null) { // figure out a object name that does work do { objectName = string.Format("{0}{1}", mapObjectContent.Name, duplicateCount); duplicateCount++; } while (Objects.Find(o => o.Name.Equals(objectName)) != null); // log a warning for the user to see //Debug.LogWarning("Renaming object \"" + mapObjectContent.Name + "\" to \"" + objectName + "\" in layer \"" + Name + "\" to make a unique name."); // save that name mapObjectContent.Name = objectName; } mapObjectContent.CreateTileObject(tiledMap, Name, layerDepth, materials); AddObject(mapObjectContent); } }