private XElement CreateCollisionElementForLayer(TmxLayer layer)
        {
            // Collision elements look like this
            // (Can also have EdgeCollider2Ds)
            //      <GameOject name="Collision">
            //        <PolygonCollider2D>
            //          <Path>list of points</Path>
            //          <Path>another list of points</Path>
            //        </PolygonCollider2D>
            //      </GameOject>

            LayerClipper.TransformPointFunc xfFunc =
                delegate(float x, float y)
            {
                // Transform point to Unity space
                PointF pointUnity3d       = PointFToUnityVector_NoScale(new PointF(x, y));
                ClipperLib.IntPoint point = new ClipperLib.IntPoint(pointUnity3d.X, pointUnity3d.Y);
                return(point);
            };

            LayerClipper.ProgressFunc progFunc =
                delegate(string prog)
            {
                Program.WriteLine(prog);
            };

            ClipperLib.PolyTree solution = LayerClipper.ExecuteClipper(this.tmxMap, layer, xfFunc, progFunc);

            // Add our polygon and edge colliders
            List <XElement> polyColliderElements = new List <XElement>();

            if (layer.IsExportingConvexPolygons())
            {
                AddPolygonCollider2DElements_Convex(solution, polyColliderElements);
            }
            else
            {
                AddPolygonCollider2DElements_Complex(solution, polyColliderElements);
            }

            AddEdgeCollider2DElements(ClipperLib.Clipper.OpenPathsFromPolyTree(solution), polyColliderElements);

            if (polyColliderElements.Count() == 0)
            {
                // No collisions on this layer
                return(null);
            }

            XElement gameObjectCollision =
                new XElement("GameObject",
                             new XAttribute("name", "Collision"),
                             polyColliderElements);

            return(gameObjectCollision);
        }
Beispiel #2
0
        private void DrawLayerColliders(Graphics g, TmxLayer layer, Color polyColor, Color lineColor)
        {
            LayerClipper.TransformPointFunc xfFunc   = (x, y) => new ClipperLib.IntPoint(x, y);
            LayerClipper.ProgressFunc       progFunc = (prog) => { }; // do nothing

            ClipperLib.PolyTree solution = LayerClipper.ExecuteClipper(this.tmxMap, layer, xfFunc, progFunc);

            float inverseScale = 1.0f / this.scale;

            if (inverseScale > 1)
            {
                inverseScale = 1;
            }

            using (GraphicsPath path = new GraphicsPath())
                using (Pen pen = new Pen(lineColor, 2.0f * inverseScale))
                    using (Brush brush = new HatchBrush(HatchStyle.Percent60, polyColor, Color.Transparent))
                    {
                        pen.Alignment = PenAlignment.Inset;

                        // Draw all closed polygons
                        // First, add them to the path
                        // (But are we using convex polygons are complex polygons?
                        var polygons = layer.IsExportingConvexPolygons() ? LayerClipper.SolutionPolygons_Simple(solution) : LayerClipper.SolutionPolygons_Complex(solution);
                        foreach (var pointfArray in polygons)
                        {
                            path.AddPolygon(pointfArray);
                        }

                        // Then, fill and draw the path full of polygons
                        if (path.PointCount > 0)
                        {
                            g.FillPath(brush, path);
                            g.DrawPath(pen, path);
                        }

                        // Draw all lines (open polygons)
                        path.Reset();
                        foreach (var points in ClipperLib.Clipper.OpenPathsFromPolyTree(solution))
                        {
                            var pointfs = points.Select(pt => new PointF(pt.X, pt.Y));
                            path.StartFigure();
                            path.AddLines(pointfs.ToArray());
                        }
                        if (path.PointCount > 0)
                        {
                            g.DrawPath(pen, path);
                        }
                    }
        }
        private void AddPolygonCollider2DElements_Convex(ClipperLib.PolyTree solution, List <XElement> xmlList)
        {
            // This may generate many convex polygons as opposed to one "complicated" one
            var polygons = LayerClipper.SolutionPolygons_Simple(solution);

            // Each PointF array is a polygon with a single path
            foreach (var pointfArray in polygons)
            {
                string   data        = String.Join(" ", pointfArray.Select(pt => String.Format("{0},{1}", pt.X * Tiled2Unity.Settings.Scale, pt.Y * Tiled2Unity.Settings.Scale)));
                XElement pathElement = new XElement("Path", data);

                XElement polyColliderElement = new XElement("PolygonCollider2D", pathElement);
                xmlList.Add(polyColliderElement);
            }
        }
        private void DrawLayerColliders(Graphics g, TmxLayer layer, Color polyColor, Color lineColor)
        {
            LayerClipper.TransformPointFunc xfFunc   = (x, y) => new ClipperLib.IntPoint(x, y);
            LayerClipper.ProgressFunc       progFunc = (prog) => { }; // do nothing

            ClipperLib.PolyTree solution = LayerClipper.ExecuteClipper(this.tmxMap, layer, xfFunc, progFunc);

            using (GraphicsPath path = new GraphicsPath())
                using (Pen pen = new Pen(lineColor, 1.0f))
                    using (Brush brush = new HatchBrush(HatchStyle.ForwardDiagonal, lineColor, polyColor))
                    {
                        pen.Alignment = PenAlignment.Inset;

                        // Draw all closed polygons
                        foreach (var points in ClipperLib.Clipper.ClosedPathsFromPolyTree(solution))
                        {
                            var pointfs = points.Select(pt => new PointF(pt.X, pt.Y));
                            path.AddPolygon(pointfs.ToArray());
                        }
                        if (path.PointCount > 0)
                        {
                            g.FillPath(brush, path);
                            g.DrawPath(pen, path);
                        }

                        // Draw all lines (open polygons)
                        path.Reset();
                        foreach (var points in ClipperLib.Clipper.OpenPathsFromPolyTree(solution))
                        {
                            var pointfs = points.Select(pt => new PointF(pt.X, pt.Y));
                            path.StartFigure();
                            path.AddLines(pointfs.ToArray());
                        }
                        if (path.PointCount > 0)
                        {
                            g.DrawPath(pen, path);
                        }
                    }
        }
        private XElement CreateCollisionElementForLayer(TmxLayer layer)
        {
            // Collision elements look like this
            // (Can also have EdgeCollider2Ds)
            //      <GameOject name="Collision">
            //        <PolygonCollider2D>
            //          <Path>list of points</Path>
            //          <Path>another list of points</Path>
            //        </PolygonCollider2D>
            //      </GameOject>

            LayerClipper.TransformPointFunc xfFunc =
                delegate(float x, float y)
            {
                // Transform point to Unity space
                PointF pointUnity3d       = PointFToUnityVector_NoScale(new PointF(x, y));
                ClipperLib.IntPoint point = new ClipperLib.IntPoint(pointUnity3d.X, pointUnity3d.Y);
                return(point);
            };

            LayerClipper.ProgressFunc progFunc =
                delegate(string prog)
            {
                Logger.WriteLine(prog);
            };

            ClipperLib.PolyTree solution = LayerClipper.ExecuteClipper(this.tmxMap, layer, xfFunc, progFunc);

            var paths = ClipperLib.Clipper.ClosedPathsFromPolyTree(solution);

            if (paths.Count >= MaxNumberOfSafePaths)
            {
                StringBuilder warning = new StringBuilder();
                warning.AppendFormat("Layer '{0}' has a large number of polygon paths ({1}).", layer.Name, paths.Count);
                warning.AppendLine("  Importing this layer may be slow in Unity. (Can take an hour or more for +1000 paths.)");
                warning.AppendLine("  Check polygon/rectangle objects in Tile Collision Editor in Tiled and use 'Snap to Grid' or 'Snap to Fine Grid'.");
                warning.AppendLine("  You want colliders to be set up so they can be merged with colliders on neighboring tiles, reducing path count considerably.");
                warning.AppendLine("  In some cases the size of the map may need to be reduced.");
                Logger.WriteWarning(warning.ToString());
            }

            // Add our polygon and edge colliders
            List <XElement> polyColliderElements = new List <XElement>();

            if (layer.IsExportingConvexPolygons())
            {
                AddPolygonCollider2DElements_Convex(solution, polyColliderElements);
            }
            else
            {
                AddPolygonCollider2DElements_Complex(solution, polyColliderElements);
            }

            AddEdgeCollider2DElements(ClipperLib.Clipper.OpenPathsFromPolyTree(solution), polyColliderElements);

            if (polyColliderElements.Count() == 0)
            {
                // No collisions on this layer
                return(null);
            }

            XElement gameObjectCollision =
                new XElement("GameObject",
                             new XAttribute("name", "Collision"),
                             polyColliderElements);

            // Collision layer may have a name and "unity physics layer" to go with it
            // (But not if we're using unity:layer override)
            if (String.IsNullOrEmpty(layer.UnityLayerOverrideName) && !String.IsNullOrEmpty(layer.Name))
            {
                gameObjectCollision.SetAttributeValue("name", "Collision_" + layer.Name);
                gameObjectCollision.SetAttributeValue("layer", layer.Name);
            }

            return(gameObjectCollision);
        }