evershade/Packages/super-tiled2unity.v2.2.0/Editor/Collision/CollisionClipper.cs

98 lines
3.1 KiB
C#

using System.Collections.Generic;
using System.Linq;
using SuperTiled2Unity.Editor.ClipperLib;
using SuperTiled2Unity.Editor.Geometry;
using UnityEngine;
namespace SuperTiled2Unity.Editor
{
public class CollisionClipper
{
private const float Multiplier = 1024.0f;
private const float InvMultiplier = 1.0f / Multiplier;
private Clipper m_Clipper = new Clipper();
private List<Vector2[]> m_RawOpenPaths = new List<Vector2[]>();
// Once the clipper is executed we have our list of processed closed and open paths
public List<Vector2[]> ClosedPaths { get; private set; }
public List<Vector2[]> OpenPaths { get; private set; }
public void AddClosedPath(Vector2[] points)
{
var path = ToClipperSpace(points);
m_Clipper.AddPath(path, PolyType.ptSubject, true);
}
public void AddOpenPath(Vector2[] points)
{
// Open paths do not get clipped but we gather them so they can be combined when we execute
m_RawOpenPaths.Add(points);
}
public void Execute()
{
PolyTree solution = new PolyTree();
m_Clipper.Execute(ClipType.ctUnion, solution, PolyFillType.pftNonZero, PolyFillType.pftEvenOdd);
AddConvexPolygonsFromSolution(solution);
CombineLines();
}
private void AddConvexPolygonsFromSolution(PolyTree solution)
{
ClosedPaths = new List<Vector2[]>();
// Triangulate the solution
var triangulator = new Triangulator();
var triangles = triangulator.TriangulateClipperSolution(solution);
// Gather triangles into a collection of convex polygons
var composition = new ComposeConvexPolygons();
var convexPolygons = composition.Compose(triangles);
foreach (var poly in convexPolygons)
{
var transformed = FromClipperSpace(poly);
ClosedPaths.Add(transformed);
}
}
private void CombineLines()
{
OpenPaths = new List<Vector2[]>();
var reduction = new PolylineReduction();
foreach (var line in m_RawOpenPaths)
{
var transformed = ToClipperSpace(line);
reduction.AddLine(transformed);
}
var polyLines = reduction.Reduce();
foreach (var lines in polyLines)
{
var transformed = FromClipperSpace(lines);
OpenPaths.Add(transformed);
}
}
private List<IntPoint> ToClipperSpace(Vector2[] points)
{
return points.Select(pt => new IntPoint(pt.x * Multiplier, pt.y * Multiplier)).ToList();
}
private Vector2[] FromClipperSpace(List<IntPoint> points)
{
return points.Select(pt => new Vector2(pt.X * InvMultiplier, pt.Y * InvMultiplier)).ToArray();
}
private Vector2[] FromClipperSpace(IEnumerable<Vector2> points)
{
return points.Select(pt => new Vector2(pt.x * InvMultiplier, pt.y * InvMultiplier)).ToArray();
}
}
}