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); }
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 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); }
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); 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."); Program.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; }
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); } } }