using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;
namespace MoreMountains.Tools
{
///
/// A class that lets you create polygon collider 2D out of mesh filters
///
public class MMMeshToPolygonCollider2D : MonoBehaviour
{
///
/// Generates a PolygonCollider2D out of a meshfilter
///
///
private static void GeneratePolygonCollider2D(MeshFilter meshFilter)
{
// we validate our mesh
if (!ValidateMesh(meshFilter))
{
return;
}
// we grab or create our PolygonCollider2D
PolygonCollider2D polygonCollider2D = InitializePolygonCollider2D(meshFilter);
if (polygonCollider2D == null)
{
return;
}
Vector3[] vectors = MeshFilterToVectors(meshFilter);
Vector2[] newPoints = VectorsToPoints(vectors);
EditorUtility.SetDirty(polygonCollider2D);
polygonCollider2D.SetPath(0, newPoints);
}
///
/// Takes an array of vectors and outputs points
///
///
///
private static Vector2[] VectorsToPoints(Vector3[] vectors)
{
List newColliderVertices = new List();
for (int i = 0; i < vectors.Length; i++)
{
newColliderVertices.Add(new Vector2(vectors[i].x, vectors[i].y));
}
Vector2[] newPoints = newColliderVertices.Distinct().ToArray();
return newPoints;
}
///
/// Turns a meshfilter into an array of vectors
///
///
///
private static Vector3[] MeshFilterToVectors(MeshFilter meshFilter)
{
List vertices = new List();
meshFilter.sharedMesh.GetVertices(vertices);
List boundaryPath = MMGeometry.GetEdges(meshFilter.sharedMesh.triangles).FindBoundary().SortEdges();
Vector3[] vectors = new Vector3[boundaryPath.Count];
for (int i = 0; i < boundaryPath.Count; i++)
{
vectors[i] = vertices[boundaryPath[i].Vertice1];
}
return vectors;
}
///
/// Grabs or creates a polygon collider 2D
///
///
///
private static PolygonCollider2D InitializePolygonCollider2D(MeshFilter meshFilter)
{
PolygonCollider2D polygonCollider2D = meshFilter.GetComponent();
if (polygonCollider2D == null)
{
polygonCollider2D = meshFilter.gameObject.AddComponent();
}
polygonCollider2D.pathCount = 1;
return polygonCollider2D;
}
///
/// Makes sure that
///
///
///
private static bool ValidateMesh(MeshFilter meshFilter)
{
if (meshFilter.sharedMesh == null)
{
Debug.LogWarning("[MMMeshToPolygonCollider2D] "
+ meshFilter.gameObject.name
+ " needs to have at least a mesh set on its mesh filter component.");
return false;
}
return true;
}
///
/// A method meant to be called via the Tools menu, that will go through all mesh colliders on an object and generate a polygon collider2D out of it
///
[MenuItem("Tools/More Mountains/Collisions/Generate PolygonCollider2D", false, 601)]
public static void GeneratePolygonCollider2DMenu()
{
Transform activeTransform = Selection.activeTransform;
if (activeTransform == null)
{
Debug.LogWarning("[MMMeshToPolygonCollider2D] You need to select a gameobject first.");
return;
}
EditorSceneManager.MarkSceneDirty(activeTransform.gameObject.scene);
MeshFilter[] meshFilters = activeTransform.GetComponentsInChildren();
foreach (MeshFilter meshFilter in meshFilters)
{
GeneratePolygonCollider2D(meshFilter);
}
}
}
}