Ejemplo n.º 1
0
        private List <XElement> CreateAssignMaterialsElements()
        {
            // Need to match all "submeshes" with a material
            // The material will have the same name as the texture
            // Each "submesh" is a Layer+Texture combination since Wavefront Obj meshes support only 1 set of texture coordinates
            var faces = from layer in tmxMap.Layers
                        where layer.Visible == true
                        from y in Enumerable.Range(0, layer.Height)
                        from x in Enumerable.Range(0, layer.Width)
                        let tileId = layer.GetTileIdAt(x, y)
                                     where tileId != 0
                                     let tile = this.tmxMap.Tiles[tileId]
                                                select new
            {
                LayerName        = layer.UniqueName,
                ImageName        = Path.GetFileNameWithoutExtension(tile.TmxImage.Path),
                TransparentColor = tile.TmxImage.TransparentColor,
                SortingLayer     = layer.Properties.GetPropertyValueAsString("unity:sortingLayerName", ""),
                SortingOrder     = layer.Properties.GetPropertyValueAsInt("unity:sortingOrder", tmxMap.Layers.IndexOf(layer)),
            };

            var groups = from f in faces
                         group f by TiledMapExpoterUtils.UnityFriendlyMeshName(tmxMap, f.LayerName, f.ImageName);

            var assignments = from g in groups
                              select new
            {
                MeshName         = g.Key,
                MaterialName     = g.First().ImageName,
                TransparentColor = g.First().TransparentColor,
                SortingLayer     = g.First().SortingLayer,
                SortingOrder     = g.First().SortingOrder,
            };

            List <XElement> elements = new List <XElement>();

            foreach (var ass in assignments)
            {
                XElement assignment =
                    new XElement("AssignMaterial",
                                 new XAttribute("mesh", ass.MeshName),
                                 new XAttribute("material", ass.MaterialName),
                                 new XAttribute("sortingLayerName", ass.SortingLayer),
                                 new XAttribute("sortingOrder", ass.SortingOrder));

                // Is there a transparent color key?
                if (!String.IsNullOrEmpty(ass.TransparentColor))
                {
                    assignment.SetAttributeValue("alphaColorKey", ass.TransparentColor);
                }

                elements.Add(assignment);
            }
            return(elements);
        }
Ejemplo n.º 2
0
        private List <XElement> CreateMeshElementsForLayer(TmxLayer layer)
        {
            // Mesh elements look like this:
            // <GameObject copy="LayerName+TilesetName" />
            // (The importer in Unity will look a submesh of that name and copy it to our prefab)
            // (This is complicated by potential tile animations now)

            var meshes = from rawTileId in layer.TileIds
                         where rawTileId != 0
                         let tileId                                                        = TmxMath.GetTileIdWithoutFlags(rawTileId)
                                                            let tile                       = this.tmxMap.Tiles[tileId]
                                                                                  let name = TiledMapExpoterUtils.UnityFriendlyMeshName(tmxMap, layer.UniqueName, Path.GetFileNameWithoutExtension(tile.TmxImage.Path))
                                                                                             group tile.Animation by name into meshGroup
                                                                                             select meshGroup;

            List <XElement> xmlMeshes = new List <XElement>();

            foreach (var m in meshes)
            {
                XElement xmlMesh = new XElement("GameObject", new XAttribute("copy", m.Key));

                // Do we have any animations?
                var animations = m.Distinct();
                foreach (var anim in animations)
                {
                    if (anim != null)
                    {
                        XElement xmlAnim = new XElement("TileAnimator");
                        foreach (var frame in anim.Frames)
                        {
                            xmlAnim.Add(new XElement("Frame", new XAttribute("vertex_z", frame.UniqueFrameId * Program.Vertex_ZScale), new XAttribute("duration", frame.DurationMs)));
                        }
                        xmlMesh.Add(xmlAnim);
                    }
                }

                xmlMeshes.Add(xmlMesh);
            }

            return(xmlMeshes);
        }
Ejemplo n.º 3
0
        private StringWriter BuildObjString()
        {
            // Creates the text for a Wavefront OBJ file for the TmxMap
            StringWriter objWriter = new StringWriter();

            // Gather the information for every face
            var faces = from layer in this.tmxMap.Layers
                        where layer.Visible == true
                        where layer.Properties.GetPropertyValueAsBoolean("unity:collisionOnly", false) == false

                        // Draw order forces us to visit tiles in a particular order
                        from y in (this.tmxMap.DrawOrderVertical == 1) ? Enumerable.Range(0, layer.Height) : Enumerable.Range(0, layer.Height).Reverse()
                        from x in (this.tmxMap.DrawOrderHorizontal == 1) ? Enumerable.Range(0, layer.Width) : Enumerable.Range(0, layer.Width).Reverse()

                        let rawTileId = layer.GetRawTileIdAt(x, y)
                                        let tileId = TmxMath.GetTileIdWithoutFlags(rawTileId)
                                                     where tileId != 0
                                                     let fd                                              = TmxMath.IsTileFlippedDiagonally(rawTileId)
                                                                                let fh                   = TmxMath.IsTileFlippedHorizontally(rawTileId)
                                                                                                  let fv = TmxMath.IsTileFlippedVertically(rawTileId)
                                                                                                           let animTile = this.tmxMap.Tiles[tileId]

                                                                                                                          // Enumerate through all frames of a tile. (Tiles without animation are treated as a single frame)
                                                                                                                          from frame in TileFrame.EnumerateFramesFromTile(animTile, this.tmxMap)
                                                                                                                          select new
            {
                LayerName          = layer.UniqueName,
                Vertices           = CalculateFaceVertices(this.tmxMap.GetMapPositionAt(x, y), frame.Tile.TileSize, this.tmxMap.TileHeight, frame.Position_z),
                TextureCoordinates = CalculateFaceTextureCoordinates(frame.Tile, fd, fh, fv),
                ImagePath          = frame.Tile.TmxImage.Path,
                ImageName          = Path.GetFileNameWithoutExtension(frame.Tile.TmxImage.Path),
            };

            // We have all the information we need now to build our list of vertices, texture coords, and grouped faces
            // (Faces are grouped by LayerName.TextureName combination because Wavefront Obj only supports one texture per face)
            objWriter.WriteLine("# Wavefront OBJ file automatically generated by Tiled2Unity");
            objWriter.WriteLine();

            // We may have a ton of vertices so use a set right now
            HashSet <Vector3D> vertexSet = new HashSet <Vector3D>();

            Program.WriteLine("Building face vertices");
            foreach (var face in faces)
            {
                // Index the vertices
                foreach (var v in face.Vertices)
                {
                    vertexSet.Add(v);
                }
            }

            HashSet <PointF> textureCoordinateSet = new HashSet <PointF>();

            Program.WriteLine("Building face texture coordinates");
            foreach (var face in faces)
            {
                // Index the texture coordinates
                foreach (var tc in face.TextureCoordinates)
                {
                    textureCoordinateSet.Add(tc);
                }
            }

            // Write the indexed vertices
            Program.WriteLine("Writing indexed vertices");
            IList <Vector3D> vertices = vertexSet.ToList();

            objWriter.WriteLine("# Vertices (Count = {0})", vertices.Count);
            foreach (var v in vertices)
            {
                objWriter.WriteLine("v {0} {1} {2}", v.X, v.Y, v.Z);
            }
            objWriter.WriteLine();

            // Write the indexed texture coordinates
            Program.WriteLine("Writing indexed texture coordinates");
            IList <PointF> textureCoordinates = textureCoordinateSet.ToList();

            objWriter.WriteLine("# Texture Coorindates (Count = {0})", textureCoordinates.Count);
            foreach (var vt in textureCoordinates)
            {
                objWriter.WriteLine("vt {0} {1}", vt.X, vt.Y);
            }
            objWriter.WriteLine();

            // Write the one indexed normal
            objWriter.WriteLine("# Normal");
            objWriter.WriteLine("vn 0 0 -1");
            objWriter.WriteLine();

            // Group faces by Layer+TileSet
            var groups = from f in faces
                         group f by TiledMapExpoterUtils.UnityFriendlyMeshName(tmxMap, f.LayerName, f.ImageName);

            // Write out the faces
            objWriter.WriteLine("# Groups (Count = {0})", groups.Count());

            // Need dictionaries with index as value.
            var vertexDict   = Enumerable.Range(0, vertices.Count()).ToDictionary(i => vertices[i], i => i);
            var texCoordDict = Enumerable.Range(0, textureCoordinates.Count()).ToDictionary(i => textureCoordinates[i], i => i);

            foreach (var g in groups)
            {
                Program.WriteLine("Writing '{0}' mesh group", g.Key);

                objWriter.WriteLine("g {0}", g.Key);
                foreach (var f in g)
                {
                    objWriter.Write("f ");
                    for (int i = 0; i < 4; ++i)
                    {
                        int vertexIndex            = vertexDict[f.Vertices[i]] + 1;
                        int textureCoordinateIndex = texCoordDict[f.TextureCoordinates[i]] + 1;

                        objWriter.Write(" {0}/{1}/1 ", vertexIndex, textureCoordinateIndex);
                    }
                    objWriter.WriteLine();
                }
            }

            Program.WriteLine("Done writing Wavefront Obj data for '{0}'", tmxMap.Name);

            return(objWriter);
        }