Beispiel #1
0
        private PointF[] CalculateFaceVertices(Point mapLocation, Size tileSize, int mapTileHeight, PointF offset)
        {
            // Location on map is complicated by tiles that are 'higher' than the tile size given for the overall map
            mapLocation.Offset(0, -tileSize.Height + mapTileHeight);

            PointF pt0 = mapLocation;
            PointF pt1 = PointF.Add(mapLocation, new Size(tileSize.Width, 0));
            PointF pt2 = PointF.Add(mapLocation, tileSize);
            PointF pt3 = PointF.Add(mapLocation, new Size(0, tileSize.Height));

            // Apply the tile offset

            pt0 = TmxMath.AddPoints(pt0, offset);
            pt1 = TmxMath.AddPoints(pt1, offset);
            pt2 = TmxMath.AddPoints(pt2, offset);
            pt3 = TmxMath.AddPoints(pt3, offset);

            // We need to use ccw winding for Wavefront objects
            PointF[] vertices = new PointF[4];
            vertices[3] = PointFToObjVertex(pt0);
            vertices[2] = PointFToObjVertex(pt1);
            vertices[1] = PointFToObjVertex(pt2);
            vertices[0] = PointFToObjVertex(pt3);
            return(vertices);
        }
Beispiel #2
0
        protected override void InternalFromXml(System.Xml.Linq.XElement xml, TmxMap tmxMap)
        {
            // Get the tile
            uint gid = TmxHelper.GetAttributeAsUInt(xml, "gid");

            this.FlippedHorizontal = TmxMath.IsTileFlippedHorizontally(gid);
            this.FlippedVertical   = TmxMath.IsTileFlippedVertically(gid);
            uint rawTileId = TmxMath.GetTileIdWithoutFlags(gid);

            this.Tile = tmxMap.Tiles[rawTileId];

            // The tile needs to have a mesh on it.
            // Note: The tile may already be referenced by another TmxObjectTile instance, and as such will have its mesh data already made
            if (this.Tile.Meshes.Count() == 0)
            {
                this.Tile.Meshes = TmxMesh.FromTmxTile(this.Tile, tmxMap);
            }

            // Check properties for layer placement
            if (this.Properties.PropertyMap.ContainsKey("unity:sortingLayerName"))
            {
                this.SortingLayerName = this.Properties.GetPropertyValueAsString("unity:sortingLayerName");
            }
            if (this.Properties.PropertyMap.ContainsKey("unity:sortingOrder"))
            {
                this.SortingOrder = this.Properties.GetPropertyValueAsInt("unity:sortingOrder");
            }
        }
Beispiel #3
0
 private void ParseImageLayerXml(XElement xml)
 {
     if (xml.Element("image") == null)
     {
         Logger.WriteWarning("Image Layer '{0}' is being ignored since it has no image.", base.Name);
         base.Ignore = IgnoreSettings.True;
     }
     else
     {
         Width  = 1;
         Height = 1;
         string  imagePath = TmxHelper.GetAttributeAsFullPath(xml.Element("image"), "source");
         TmxTile value     = base.ParentMap.Tiles.First((KeyValuePair <uint, TmxTile> t) => t.Value.TmxImage.AbsolutePath.ToLower() == imagePath.ToLower()).Value;
         Data = new TmxData(this);
         TmxChunk tmxChunk = new TmxChunk(Data);
         tmxChunk.X      = 0;
         tmxChunk.Y      = 0;
         tmxChunk.Width  = 1;
         tmxChunk.Height = 1;
         tmxChunk.TileIds.Add(value.GlobalId);
         Data.Chunks.Add(tmxChunk);
         PointF offset = base.Offset;
         offset.Y -= (float)base.ParentMap.TileHeight;
         offset.Y += (float)value.TmxImage.Size.Height;
         PointF pointF = TmxMath.TileCornerInScreenCoordinates(base.ParentMap, 0, 0);
         offset.X   -= pointF.X;
         offset.Y   -= pointF.Y;
         offset.X   += TmxHelper.GetAttributeAsFloat(xml, "x", 0f);
         offset.Y   += TmxHelper.GetAttributeAsFloat(xml, "y", 0f);
         base.Offset = offset;
     }
 }
Beispiel #4
0
 private void ReadTileIds(XElement xml)
 {
     TileIds.Clear();
     if (ParentData.Encoding == DataEncoding.Xml)
     {
         ReadTileIds_Xml(xml);
     }
     else if (ParentData.Encoding == DataEncoding.Csv)
     {
         ReadTiledIds_Csv(xml.Value);
     }
     else if (ParentData.Encoding == DataEncoding.Base64)
     {
         ReadTileIds_Base64(xml.Value);
     }
     else
     {
         TmxException.ThrowFormat("Unsupported encoding for chunk data in layer '{0}'", ParentData.ParentLayer);
     }
     for (int i = 0; i < TileIds.Count; i++)
     {
         uint tileId = TileIds[i];
         tileId = TmxMath.GetTileIdWithoutFlags(tileId);
         if (!ParentData.ParentLayer.ParentMap.Tiles.ContainsKey(tileId))
         {
             TileIds[i] = 0u;
         }
     }
 }
Beispiel #5
0
        private PointF[] CalculateFaceVertices_TileObject(Size tileSize, PointF offset)
        {
            // Tile Object vertices are not concerned about where they are placed in the world
            PointF origin = PointF.Empty;

            PointF pt0 = origin;
            PointF pt1 = PointF.Add(origin, new Size(tileSize.Width, 0));
            PointF pt2 = PointF.Add(origin, tileSize);
            PointF pt3 = PointF.Add(origin, new Size(0, tileSize.Height));

            // Apply the tile offset

            pt0 = TmxMath.AddPoints(pt0, offset);
            pt1 = TmxMath.AddPoints(pt1, offset);
            pt2 = TmxMath.AddPoints(pt2, offset);
            pt3 = TmxMath.AddPoints(pt3, offset);

            // We need to use ccw winding for Wavefront objects
            PointF[] vertices = new PointF[4];
            vertices[3] = PointFToObjVertex(pt0);
            vertices[2] = PointFToObjVertex(pt1);
            vertices[1] = PointFToObjVertex(pt2);
            vertices[0] = PointFToObjVertex(pt3);
            return(vertices);
        }
Beispiel #6
0
 private void BuildCollisionLayers_ByObjectType()
 {
     for (int i = 0; i < Data.Chunks.Count; i++)
     {
         TmxChunk tmxChunk = Data.Chunks[i];
         for (int j = 0; j < tmxChunk.TileIds.Count; j++)
         {
             uint num = tmxChunk.TileIds[j];
             if (num != 0)
             {
                 uint tileIdWithoutFlags = TmxMath.GetTileIdWithoutFlags(num);
                 foreach (TmxObject @object in base.ParentMap.Tiles[tileIdWithoutFlags].ObjectGroup.Objects)
                 {
                     if (@object is TmxHasPoints)
                     {
                         TmxLayer tmxLayer = CollisionLayers.Find((TmxLayer l) => string.Compare(l.Name, @object.Type, true) == 0);
                         if (tmxLayer == null)
                         {
                             tmxLayer = new TmxLayer(null, base.ParentMap);
                             CollisionLayers.Add(tmxLayer);
                             tmxLayer.Name       = @object.Type;
                             tmxLayer.Offset     = base.Offset;
                             tmxLayer.Width      = Width;
                             tmxLayer.Height     = Height;
                             tmxLayer.Ignore     = base.Ignore;
                             tmxLayer.Properties = base.Properties;
                             tmxLayer.Data       = Data.MakeEmptyCopy(tmxLayer);
                         }
                         tmxLayer.Data.Chunks[i].TileIds[j] = num;
                     }
                 }
             }
         }
     }
 }
Beispiel #7
0
        protected override void InternalFromXml(System.Xml.Linq.XElement xml, TmxMap tmxMap)
        {
            Debug.Assert(xml.Name == "object");
            Debug.Assert(xml.Element("polyline") != null);

            var points = from pt in xml.Element("polyline").Attribute("points").Value.Split(' ')
                         let x                 = float.Parse(pt.Split(',')[0])
                                         let y = float.Parse(pt.Split(',')[1])
                                                 select new PointF(x, y);

            // If there are only 2 points in the polyline then we force a midpoint between them
            // This is because the clipper library is rejecting polylines unless there is 3 or more points
            if (points.Count() == 2)
            {
                var A = points.First();
                var B = points.Last();
                var M = TmxMath.MidPoint(A, B);
                this.Points = new List <PointF>()
                {
                    A, M, B
                };
            }
            else
            {
                this.Points = points.ToList();
            }
        }
Beispiel #8
0
        public static TmxObject FromXml(XElement xml, TmxObjectGroup tmxObjectGroup, TmxMap tmxMap)
        {
            Logger.WriteVerbose("Parsing object ...");
            uint attributeAsUInt = TmxHelper.GetAttributeAsUInt(xml, "tid", 0u);

            if (attributeAsUInt != 0 && tmxMap.Templates.TryGetValue(attributeAsUInt, out TgxTemplate value))
            {
                xml    = value.Templatize(xml);
                tmxMap = value.TemplateGroupMap;
            }
            TmxObject tmxObject = null;

            if (xml.Element("ellipse") != null)
            {
                tmxObject = new TmxObjectEllipse();
            }
            else if (xml.Element("polygon") != null)
            {
                tmxObject = new TmxObjectPolygon();
            }
            else if (xml.Element("polyline") != null)
            {
                tmxObject = new TmxObjectPolyline();
            }
            else if (xml.Attribute("gid") != null)
            {
                uint attributeAsUInt2 = TmxHelper.GetAttributeAsUInt(xml, "gid");
                attributeAsUInt2 = TmxMath.GetTileIdWithoutFlags(attributeAsUInt2);
                if (tmxMap.Tiles.ContainsKey(attributeAsUInt2))
                {
                    tmxObject = new TmxObjectTile();
                }
                else
                {
                    Logger.WriteWarning("Tile Id {0} not found in tilesets. Using a rectangle instead.\n{1}", attributeAsUInt2, xml.ToString());
                    tmxObject = new TmxObjectRectangle();
                }
            }
            else
            {
                tmxObject = new TmxObjectRectangle();
            }
            tmxObject.Id                = TmxHelper.GetAttributeAsInt(xml, "id", 0);
            tmxObject.Name              = TmxHelper.GetAttributeAsString(xml, "name", "");
            tmxObject.Type              = TmxHelper.GetAttributeAsString(xml, "type", "");
            tmxObject.Visible           = (TmxHelper.GetAttributeAsInt(xml, "visible", 1) == 1);
            tmxObject.ParentObjectGroup = tmxObjectGroup;
            float attributeAsFloat  = TmxHelper.GetAttributeAsFloat(xml, "x");
            float attributeAsFloat2 = TmxHelper.GetAttributeAsFloat(xml, "y");
            float attributeAsFloat3 = TmxHelper.GetAttributeAsFloat(xml, "width", 0f);
            float attributeAsFloat4 = TmxHelper.GetAttributeAsFloat(xml, "height", 0f);
            float attributeAsFloat5 = TmxHelper.GetAttributeAsFloat(xml, "rotation", 0f);

            tmxObject.Position   = new PointF(attributeAsFloat, attributeAsFloat2);
            tmxObject.Size       = new SizeF(attributeAsFloat3, attributeAsFloat4);
            tmxObject.Rotation   = attributeAsFloat5;
            tmxObject.Properties = TmxProperties.FromXml(xml);
            tmxObject.InternalFromXml(xml, tmxMap);
            return(tmxObject);
        }
        private void DrawPolygon(Graphics g, Pen pen, Brush brush, TmxObjectPolygon tmxPolygon)
        {
            var points = TmxMath.GetPointsInMapSpace(this.tmxMap, tmxPolygon).ToArray();

            g.FillPolygon(brush, points);
            g.DrawPolygon(pen, points);
        }
Beispiel #10
0
        static public Point TileCornerInGridCoordinates(TmxMap tmxMap, int x, int y)
        {
            // Support different map display types (orthographic, isometric, etc..)
            // Note: simulates "tileToScreenCoords" function from Tiled source
            if (tmxMap.Orientation == TmxMap.MapOrientation.Isometric)
            {
                Point point = Point.Empty;

                int origin_x = tmxMap.Height * tmxMap.TileWidth / 2;
                point.X = (x - y) * tmxMap.TileWidth / 2 + origin_x;
                point.Y = (x + y) * tmxMap.TileHeight / 2;

                return(point);
            }
            else if (tmxMap.Orientation == TmxMap.MapOrientation.Staggered || tmxMap.Orientation == TmxMap.MapOrientation.Hexagonal)
            {
                Point point = Point.Empty;

                int tileWidth  = tmxMap.TileWidth & ~1;
                int tileHeight = tmxMap.TileHeight & ~1;

                int sideLengthX = tmxMap.StaggerAxis == TmxMap.MapStaggerAxis.X ? tmxMap.HexSideLength : 0;
                int sideLengthY = tmxMap.StaggerAxis == TmxMap.MapStaggerAxis.Y ? tmxMap.HexSideLength : 0;

                int sideOffsetX = (tileWidth - sideLengthX) / 2;
                int sideOffsetY = (tileHeight - sideLengthY) / 2;

                int columnWidth = sideOffsetX + sideLengthX;
                int rowHeight   = sideOffsetY + sideLengthY;

                if (tmxMap.StaggerAxis == TmxMap.MapStaggerAxis.X)
                {
                    point.Y = y * (tileHeight + sideLengthY);
                    if (TmxMath.DoStaggerX(tmxMap, x))
                    {
                        point.Y += rowHeight;
                    }

                    point.X = x * columnWidth;
                }
                else
                {
                    point.X = x * (tileWidth + sideLengthX);
                    if (TmxMath.DoStaggerY(tmxMap, y))
                    {
                        point.X += columnWidth;
                    }

                    point.Y = y * rowHeight;
                }

                point.Offset(tileWidth / 2, 0);
                return(point);
            }

            // Default orthographic orientation
            return(new Point(x * tmxMap.TileWidth, y * tmxMap.TileHeight));
        }
Beispiel #11
0
 public TmxTile GetTileFromTileId(uint tileId)
 {
     if (tileId == 0)
     {
         return(null);
     }
     tileId = TmxMath.GetTileIdWithoutFlags(tileId);
     return(Tiles[tileId]);
 }
Beispiel #12
0
        public PointF GetCombinedOffset()
        {
            PointF pointF = Offset;

            for (TmxLayerNode parentNode = ParentNode; parentNode != null; parentNode = parentNode.ParentNode)
            {
                pointF = TmxMath.AddPoints(pointF, parentNode.Offset);
            }
            return(pointF);
        }
        private StringWriter BuildWavefrontStringForLayerMesh(TmxLayer layer, TmxMesh mesh, IEnumerable <int> horizontalRange, IEnumerable <int> verticalRange)
        {
            Logger.WriteVerbose("Building mesh obj file for '{0}'", mesh.UniqueMeshName);
            GenericListDatabase <Vertex3> vertexDatabase = new GenericListDatabase <Vertex3>();
            HashIndexOf <PointF>          uvDatabase     = new HashIndexOf <PointF>();
            StringBuilder faces = new StringBuilder();

            foreach (int y in verticalRange)
            {
                foreach (int x in horizontalRange)
                {
                    int  tileIndex = layer.GetTileIndex(x, y);
                    uint tileId    = mesh.GetTileIdAt(tileIndex);

                    // Skip blank tiles
                    if (tileId == 0)
                    {
                        continue;
                    }

                    TmxTile tile = this.tmxMap.Tiles[TmxMath.GetTileIdWithoutFlags(tileId)];

                    // What are the vertex and texture coorindates of this face on the mesh?
                    var position = this.tmxMap.GetMapPositionAt(x, y, tile);
                    var vertices = CalculateFaceVertices(position, tile.TileSize);

                    // If we're using depth shaders then we'll need to set a depth value of this face
                    float depth_z = 0.0f;
                    if (Tiled2Unity.Settings.DepthBufferEnabled)
                    {
                        depth_z = CalculateFaceDepth(position.Y + tmxMap.TileHeight, tmxMap.MapSizeInPixels.Height);
                    }

                    FaceVertices faceVertices = new FaceVertices {
                        Vertices = vertices, Depth_z = depth_z
                    };

                    // Is the tile being flipped or rotated (needed for texture cooridinates)
                    bool flipDiagonal   = TmxMath.IsTileFlippedDiagonally(tileId);
                    bool flipHorizontal = TmxMath.IsTileFlippedHorizontally(tileId);
                    bool flipVertical   = TmxMath.IsTileFlippedVertically(tileId);
                    var  uvs            = CalculateFaceTextureCoordinates(tile, flipDiagonal, flipHorizontal, flipVertical);

                    // Adds vertices and uvs to the database as we build the face strings
                    string v0 = String.Format("{0}/{1}/1", vertexDatabase.AddToDatabase(faceVertices.V0) + 1, uvDatabase.Add(uvs[0]) + 1);
                    string v1 = String.Format("{0}/{1}/1", vertexDatabase.AddToDatabase(faceVertices.V1) + 1, uvDatabase.Add(uvs[1]) + 1);
                    string v2 = String.Format("{0}/{1}/1", vertexDatabase.AddToDatabase(faceVertices.V2) + 1, uvDatabase.Add(uvs[2]) + 1);
                    string v3 = String.Format("{0}/{1}/1", vertexDatabase.AddToDatabase(faceVertices.V3) + 1, uvDatabase.Add(uvs[3]) + 1);
                    faces.AppendFormat("f {0} {1} {2} {3}\n", v0, v1, v2, v3);
                }
            }

            // We have all the data we need to build the wavefront file format
            return(CreateWavefrontWriter(mesh, vertexDatabase, uvDatabase, faces));
        }
        private XElement CreatePolygonColliderElement(TmxObjectPolygon tmxPolygon)
        {
            var points = from pt in TmxMath.GetPointsInMapSpace(this.tmxMap, tmxPolygon)
                         select PointFToUnityVector(pt);

            XElement polygonCollider =
                new XElement("PolygonCollider2D",
                             new XElement("Path", String.Join(" ", points.Select(pt => String.Format("{0},{1}", pt.X, pt.Y)))));

            return(polygonCollider);
        }
        private XElement CreateEdgeColliderElement(TmxObjectPolyline tmxPolyline)
        {
            // The points need to be transformed into unity space
            var points = from pt in TmxMath.GetPointsInMapSpace(this.tmxMap, tmxPolyline)
                         select PointFToUnityVector(pt);

            XElement edgeCollider =
                new XElement("EdgeCollider2D",
                             new XElement("Points", String.Join(" ", points.Select(pt => String.Format("{0},{1}", pt.X, pt.Y)))));

            return(edgeCollider);
        }
Beispiel #16
0
        public static List <PointF> GetPointsInMapSpace(TmxMap tmxMap, TmxHasPoints objectWithPoints)
        {
            PointF local = TmxMath.ObjectPointFToMapSpace(tmxMap, 0, 0);

            local.X = -local.X;
            local.Y = -local.Y;

            List <PointF> xfPoints = objectWithPoints.Points.Select(pt => TmxMath.ObjectPointFToMapSpace(tmxMap, pt)).ToList();

            xfPoints = xfPoints.Select(pt => TmxMath.AddPoints(pt, local)).ToList();
            return(xfPoints);
        }
Beispiel #17
0
        public PointF GetCombinedOffset()
        {
            PointF       offset = this.Offset;
            TmxLayerNode parent = this.ParentNode;

            while (parent != null)
            {
                offset = TmxMath.AddPoints(offset, parent.Offset);
                parent = parent.ParentNode;
            }

            return(offset);
        }
Beispiel #18
0
        private PointF[] CalculateFaceTextureCoordinates(TmxTile tmxTile, bool flipDiagonal, bool flipHorizontal, bool flipVertical)
        {
            Point imageLocation = tmxTile.LocationOnSource;
            Size  tileSize      = tmxTile.TileSize;
            Size  imageSize     = tmxTile.TmxImage.Size;

            PointF[] points = new PointF[4];
            points[0] = imageLocation;
            points[1] = PointF.Add(imageLocation, new Size(tileSize.Width, 0));
            points[2] = PointF.Add(imageLocation, tileSize);
            points[3] = PointF.Add(imageLocation, new Size(0, tileSize.Height));

            PointF center = new PointF(tileSize.Width * 0.5f, tileSize.Height * 0.5f);

            center.X += imageLocation.X;
            center.Y += imageLocation.Y;
            TmxMath.TransformPoints_DiagFirst(points, center, flipDiagonal, flipHorizontal, flipVertical);
            //TmxMath.TransformPoints(points, center, flipDiagonal, flipHorizontal, flipVertical);

            PointF[] coordinates = new PointF[4];
            coordinates[3] = PointToTextureCoordinate(points[0], imageSize);
            coordinates[2] = PointToTextureCoordinate(points[1], imageSize);
            coordinates[1] = PointToTextureCoordinate(points[2], imageSize);
            coordinates[0] = PointToTextureCoordinate(points[3], imageSize);

            // Apply a small bias to the "inner" edges of the texels
            // This keeps us from seeing seams
            //const float bias = 1.0f / 8192.0f;
            //const float bias = 1.0f / 4096.0f;
            //const float bias = 1.0f / 2048.0f;
            if (Program.TexelBias > 0)
            {
                float bias = 1.0f / Program.TexelBias;

                PointF[] multiply = new PointF[4];
                multiply[0] = new PointF(1, 1);
                multiply[1] = new PointF(-1, 1);
                multiply[2] = new PointF(-1, -1);
                multiply[3] = new PointF(1, -1);

                // This nudge has to be transformed too
                TmxMath.TransformPoints_DiagFirst(multiply, Point.Empty, flipDiagonal, flipHorizontal, flipVertical);

                coordinates[0] = TmxMath.AddPoints(coordinates[0], TmxMath.ScalePoints(multiply[0], bias));
                coordinates[1] = TmxMath.AddPoints(coordinates[1], TmxMath.ScalePoints(multiply[1], bias));
                coordinates[2] = TmxMath.AddPoints(coordinates[2], TmxMath.ScalePoints(multiply[2], bias));
                coordinates[3] = TmxMath.AddPoints(coordinates[3], TmxMath.ScalePoints(multiply[3], bias));
            }

            return(coordinates);
        }
Beispiel #19
0
        public void BakeRotation()
        {
            PointF[] array = new PointF[1]
            {
                PointF.Empty
            };
            TmxMath.RotatePoints(array, this);
            float x = Position.X - array[0].X;
            float y = Position.Y - array[0].Y;

            Position = new PointF(x, y);
            Position = TmxMath.Sanitize(Position);
            Rotation = 0f;
        }
        private PointF[] CalculateFaceTextureCoordinates(TmxTile tmxTile, bool flipDiagonal, bool flipHorizontal, bool flipVertical)
        {
            Point imageLocation = tmxTile.LocationOnSource;
            Size  tileSize      = tmxTile.TileSize;
            Size  imageSize     = tmxTile.TmxImage.Size;

            PointF[] points = new PointF[4];
            points[0] = imageLocation;
            points[1] = PointF.Add(imageLocation, new Size(tileSize.Width, 0));
            points[2] = PointF.Add(imageLocation, tileSize);
            points[3] = PointF.Add(imageLocation, new Size(0, tileSize.Height));

            // Transform the points with our flip flags
            PointF center = new PointF(tileSize.Width * 0.5f, tileSize.Height * 0.5f);

            center.X += imageLocation.X;
            center.Y += imageLocation.Y;
            TmxMath.TransformPoints_DiagFirst(points, center, flipDiagonal, flipHorizontal, flipVertical);

            // "Tuck in" the points a tiny bit to help avoid seams
            // This can be turned off by setting Texel Bias to zero
            // Note that selecting a texel bias that is too small or a texture that is too big may affect pixel-perfect rendering (pixel snapping in shader will help)
            float bias = 0.0f;

            PointF[] tucks = new PointF[4];
            if (Tiled2Unity.Settings.TexelBias > 0)
            {
                bias        = 1.0f / Tiled2Unity.Settings.TexelBias;
                tucks[0].X += 1.0f;
                tucks[0].Y += 1.0f;

                tucks[1].X -= 1.0f;
                tucks[1].Y += 1.0f;

                tucks[2].X -= 1.0f;
                tucks[2].Y -= 1.0f;

                tucks[3].X += 1.0f;
                tucks[3].Y -= 1.0f;
            }
            TmxMath.TransformPoints_DiagFirst(tucks, PointF.Empty, flipDiagonal, flipHorizontal, flipVertical);

            PointF[] coordinates = new PointF[4];
            coordinates[3] = TmxMath.AddPoints(PointToTextureCoordinate(points[0], imageSize), TmxMath.ScalePoint(tucks[0].X, -tucks[0].Y, bias));
            coordinates[2] = TmxMath.AddPoints(PointToTextureCoordinate(points[1], imageSize), TmxMath.ScalePoint(tucks[1].X, -tucks[1].Y, bias));
            coordinates[1] = TmxMath.AddPoints(PointToTextureCoordinate(points[2], imageSize), TmxMath.ScalePoint(tucks[2].X, -tucks[2].Y, bias));
            coordinates[0] = TmxMath.AddPoints(PointToTextureCoordinate(points[3], imageSize), TmxMath.ScalePoint(tucks[3].X, -tucks[3].Y, bias));

            return(coordinates);
        }
Beispiel #21
0
        public static TmxObjectGroup FromXml(XElement xml, TmxLayerNode parent, TmxMap tmxMap)
        {
            TmxObjectGroup tmxObjectGroup = new TmxObjectGroup(parent, tmxMap);

            tmxObjectGroup.FromXmlInternal(xml);
            tmxObjectGroup.Color = TmxHelper.GetAttributeAsColor(xml, "color", new Color32(128, 128, 128, 255));
            Logger.WriteVerbose("Parsing objects in object group '{0}'", tmxObjectGroup.Name);
            IEnumerable <TmxObject> source = from obj in xml.Elements("object")
                                             select TmxObject.FromXml(obj, tmxObjectGroup, tmxMap);

            tmxObjectGroup.Objects = (from o in source
                                      orderby TmxMath.ObjectPointFToMapSpace(tmxMap, o.Position).Y
                                      select o).ToList();
            return(tmxObjectGroup);
        }
        private PointF[] CalculateFaceTextureCoordinates(TmxTile tmxTile, bool flipDiagonal, bool flipHorizontal, bool flipVertical)
        {
            Point imageLocation = tmxTile.LocationOnSource;
            Size  tileSize      = tmxTile.TileSize;
            Size  imageSize     = tmxTile.TmxImage.Size;

            PointF[] points = new PointF[4];
            points[0] = imageLocation;
            points[1] = PointF.Add(imageLocation, new Size(tileSize.Width, 0));
            points[2] = PointF.Add(imageLocation, tileSize);
            points[3] = PointF.Add(imageLocation, new Size(0, tileSize.Height));

            PointF center = new PointF(tileSize.Width * 0.5f, tileSize.Height * 0.5f);

            center.X += imageLocation.X;
            center.Y += imageLocation.Y;
            TmxMath.TransformPoints_DiagFirst(points, center, flipDiagonal, flipHorizontal, flipVertical);
            //TmxMath.TransformPoints(points, center, flipDiagonal, flipHorizontal, flipVertical);

            PointF[] coordinates = new PointF[4];
            coordinates[3] = PointToTextureCoordinate(points[0], imageSize);
            coordinates[2] = PointToTextureCoordinate(points[1], imageSize);
            coordinates[1] = PointToTextureCoordinate(points[2], imageSize);
            coordinates[0] = PointToTextureCoordinate(points[3], imageSize);

            // Apply a small bias to the "inner" edges of the texels
            // This keeps us from seeing seams
            // (If seams continue along "outer" edges we can try applying the bias there as well)
            // Note: On Oct 25, a user was having issues with outer edges, so I brought those in as well afterall (for version 0.9.5.4)
            //const float bias = 1.0f / 8192.0f;
            //const float bias = 1.0f / 4096.0f;
            //const float bias = 1.0f / 2048.0f;
            float bias = 1.0f / Program.TexelBias;

            coordinates[0].X += bias;
            coordinates[0].Y += bias;

            coordinates[1].X -= bias;
            coordinates[1].Y += bias;

            coordinates[2].X -= bias;
            coordinates[2].Y -= bias;

            coordinates[3].X += bias;
            coordinates[3].Y -= bias;

            return(coordinates);
        }
Beispiel #23
0
        private void BuildCollisionLayers_ByObjectType()
        {
            // Find all tiles with collisions on them and put them into a "Collision Layer" of the same type
            for (int t = 0; t < this.TileIds.Length; ++t)
            {
                uint rawTileId = this.TileIds[t];
                if (rawTileId == 0)
                {
                    continue;
                }

                uint    tileId  = TmxMath.GetTileIdWithoutFlags(rawTileId);
                TmxTile tmxTile = this.TmxMap.Tiles[tileId];

                foreach (TmxObject colliderObject in tmxTile.ObjectGroup.Objects)
                {
                    if ((colliderObject is TmxHasPoints) == false)
                    {
                        continue;
                    }

                    // We have a collider object on the tile
                    // Add the tile to the Collision Layer of the matching type
                    // Or, create a new Collision Layer of this type to add this tile to
                    TmxLayer collisionLayer = this.CollisionLayers.Find(l => String.Compare(l.Name, colliderObject.Type, true) == 0);
                    if (collisionLayer == null)
                    {
                        // Create a new Collision Layer
                        collisionLayer = new TmxLayer(null, this.TmxMap);
                        this.CollisionLayers.Add(collisionLayer);

                        // The new Collision Layer has the name of the collider object and empty tiles (they will be filled with tiles that have matching collider objects)
                        collisionLayer.Name    = colliderObject.Type;
                        collisionLayer.TileIds = new uint[this.TileIds.Length];

                        // Copy over some stuff from parent layer that we need for creating collisions
                        collisionLayer.Offset     = this.Offset;
                        collisionLayer.Width      = this.Width;
                        collisionLayer.Height     = this.Height;
                        collisionLayer.Ignore     = this.Ignore;
                        collisionLayer.Properties = this.Properties;
                    }

                    // Add the tile to this collision layer
                    collisionLayer.TileIds[t] = rawTileId;
                }
            }
        }
Beispiel #24
0
        public void BakeRotation()
        {
            // Rotate (0, 0)
            PointF[] pointfs = new PointF[1] {
                PointF.Empty
            };
            TmxMath.RotatePoints(pointfs, this);

            // Bake that rotation into our position, sanitizing the result
            float x = this.Position.X - pointfs[0].X;
            float y = this.Position.Y - pointfs[0].Y;

            this.Position = new PointF(x, y);
            this.Position = TmxMath.Sanitize(this.Position);

            // Null out our rotation
            this.Rotation = 0;
        }
Beispiel #25
0
        protected override void InternalFromXml(System.Xml.Linq.XElement xml, TmxMap tmxMap)
        {
            // Get the tile
            uint gid = TmxHelper.GetAttributeAsUInt(xml, "gid");

            this.FlippedHorizontal = TmxMath.IsTileFlippedHorizontally(gid);
            this.FlippedVertical   = TmxMath.IsTileFlippedVertically(gid);
            uint rawTileId = TmxMath.GetTileIdWithoutFlags(gid);

            this.Tile = tmxMap.Tiles[rawTileId];

            // The tile needs to have a mesh on it.
            // Note: The tile may already be referenced by another TmxObjectTile instance, and as such will have its mesh data already made
            if (this.Tile.Meshes.Count() == 0)
            {
                this.Tile.Meshes = TmxMesh.FromTmxTile(this.Tile, tmxMap);
            }
        }
Beispiel #26
0
        private void AddTileObjectElements(TmxObjectTile tmxTile, XElement xmlTileObject)
        {
            // We combine the properties of the tile that is referenced and add it to our own properties
            AssignTiledProperties(tmxTile.Tile, xmlTileObject);

            // Add any colliders that might be on the tile
            foreach (TmxObject tmxObject in tmxTile.Tile.ObjectGroup.Objects)
            {
                // All the objects/colliders in our object group need to be separate game objects because they can have unique tags/layers
                XElement xmlObject = new XElement("GameObject", new XAttribute("name", tmxObject.GetNonEmptyName()));

                // Transform object locaction into map space (needed for isometric and hex modes)
                PointF   xfPosition = TmxMath.ObjectPointFToMapSpace(this.tmxMap, tmxObject.Position);
                Vector3D pos        = PointFToUnityVector(xfPosition);
                xmlObject.SetAttributeValue("x", pos.X);
                xmlObject.SetAttributeValue("y", pos.Y);
                xmlObject.SetAttributeValue("rotation", tmxObject.Rotation);

                XElement objElement = null;

                if (tmxObject.GetType() == typeof(TmxObjectRectangle))
                {
                    // Note: Tile objects have orthographic rectangles even in isometric orientations so no need to transform rectangle points
                    objElement = CreateBoxColliderElement(tmxObject as TmxObjectRectangle);
                }
                else if (tmxObject.GetType() == typeof(TmxObjectEllipse))
                {
                    objElement = CreateCircleColliderElement(tmxObject as TmxObjectEllipse, tmxTile.Tile.ObjectGroup.Name);
                }
                else if (tmxObject.GetType() == typeof(TmxObjectPolygon))
                {
                    objElement = CreatePolygonColliderElement(tmxObject as TmxObjectPolygon);
                }
                else if (tmxObject.GetType() == typeof(TmxObjectPolyline))
                {
                    objElement = CreateEdgeColliderElement(tmxObject as TmxObjectPolyline);
                }

                if (objElement != null)
                {
                    xmlTileObject.Add(objElement);
                }
            }
        }
Beispiel #27
0
        protected override void InternalFromXml(XElement xml, TmxMap tmxMap)
        {
            uint attributeAsUInt = TmxHelper.GetAttributeAsUInt(xml, "gid");

            FlippedHorizontal = TmxMath.IsTileFlippedHorizontally(attributeAsUInt);
            FlippedVertical   = TmxMath.IsTileFlippedVertically(attributeAsUInt);
            uint tileIdWithoutFlags = TmxMath.GetTileIdWithoutFlags(attributeAsUInt);

            Tile = tmxMap.Tiles[tileIdWithoutFlags];
            if (Tile.Meshes.Count() == 0)
            {
                Tile.Meshes = TmxMesh.FromTmxTile(Tile, tmxMap);
            }
            ExplicitSortingLayerName = base.Properties.GetPropertyValueAsString("unity:sortingLayerName", "");
            if (base.Properties.PropertyMap.ContainsKey("unity:sortingOrder"))
            {
                ExplicitSortingOrder = base.Properties.GetPropertyValueAsInt("unity:sortingOrder");
            }
        }
Beispiel #28
0
        private void FixTileColliderObjects(TmxMap tmxMap)
        {
            // Objects inside of tiles are colliders that will be merged with the colliders on neighboring tiles.
            // In order to promote this merging we have to perform the following clean up operations ...
            // - All rectangles objects are made into polygon objects
            // - All polygon objects will have their rotations burned into the polygon points (and Rotation set to zero)
            // - All cooridinates will be "sanitized" to make up for floating point errors due to rotation and poor placement of colliders
            // (The sanitation will round all numbers to the nearest 1/256th)

            // Replace rectangles with polygons
            for (int i = 0; i < this.ObjectGroup.Objects.Count; i++)
            {
                TmxObject tmxObject = this.ObjectGroup.Objects[i];
                if (tmxObject is TmxObjectRectangle)
                {
                    TmxObjectPolygon tmxObjectPolygon = TmxObjectPolygon.FromRectangle(tmxMap, tmxObject as TmxObjectRectangle);
                    this.ObjectGroup.Objects[i] = tmxObjectPolygon;
                }
            }

            // Burn rotation into all polygon points, sanitizing the point locations as we go
            foreach (TmxObject tmxObject in this.ObjectGroup.Objects)
            {
                TmxHasPoints tmxHasPoints = tmxObject as TmxHasPoints;
                if (tmxHasPoints != null)
                {
                    var pointfs = tmxHasPoints.Points.ToArray();

                    // Rotate our points by the rotation and position in the object
                    TmxMath.RotatePoints(pointfs, tmxObject);

                    // Sanitize our points to make up for floating point precision errors
                    pointfs = pointfs.Select(TmxMath.Sanitize).ToArray();

                    // Set the points back into the object
                    tmxHasPoints.Points = pointfs.ToList();

                    // Zero out our rotation
                    tmxObject.BakeRotation();
                }
            }
        }
        public static TmxObjectGroup FromXml(XElement xml, TmxLayerNode parent, TmxMap tmxMap)
        {
            Debug.Assert(xml.Name == "objectgroup");

            TmxObjectGroup tmxObjectGroup = new TmxObjectGroup(parent, tmxMap);

            tmxObjectGroup.FromXmlInternal(xml);

            // Color is specific to object group
            tmxObjectGroup.Color = TmxHelper.GetAttributeAsColor(xml, "color", Color.FromArgb(128, 128, 128));

            // Get all the objects
            Logger.WriteLine("Parsing objects in object group '{0}'", tmxObjectGroup.Name);
            var objects = from obj in xml.Elements("object")
                          select TmxObject.FromXml(obj, tmxObjectGroup, tmxMap);

            // The objects are ordered "visually" by Y position
            tmxObjectGroup.Objects = objects.OrderBy(o => TmxMath.ObjectPointFToMapSpace(tmxMap, o.Position).Y).ToList();

            return(tmxObjectGroup);
        }
Beispiel #30
0
        // Creates a TmxMesh from a tile (for tile objects)
        public static List <TmxMesh> FromTmxTile(TmxTile tmxTile, TmxMap tmxMap)
        {
            List <TmxMesh> meshes = new List <TmxMesh>();

            int timeMs = 0;

            foreach (var frame in tmxTile.Animation.Frames)
            {
                uint    frameTileId = frame.GlobalTileId;
                TmxTile frameTile   = tmxMap.Tiles[frameTileId];

                TmxMesh mesh = new TmxMesh();
                mesh.TileIds    = new uint[1];
                mesh.TileIds[0] = frameTileId;

                mesh.UniqueMeshName = String.Format("mesh_tile_{0}", TmxMath.GetTileIdWithoutFlags(frameTileId).ToString("D4"));
                mesh.TmxImage       = frameTile.TmxImage;
                mesh.ObjectName     = "tile_obj";

                // Keep track of the timing for this mesh (non-animating meshes will have a start time and duration of 0)
                mesh.StartTimeMs             = timeMs;
                mesh.DurationMs              = frame.DurationMs;
                mesh.FullAnimationDurationMs = tmxTile.Animation.TotalTimeMs;

                if (mesh.DurationMs != 0)
                {
                    // Decorate the name a bit with some animation details for the frame
                    mesh.ObjectName += string.Format("[{0}-{1}]", timeMs, timeMs + mesh.DurationMs);
                }

                // Advance time
                timeMs += frame.DurationMs;

                // Add the animation frame to our list of meshes
                meshes.Add(mesh);
            }

            return(meshes);
        }