Last active
September 18, 2019 19:59
-
-
Save drewcassidy/b10b674f6ed2e4b01860017074b9de31 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections.Generic; | |
using System.Linq; | |
using System.Reflection; | |
using UnityEditor; | |
using UnityEngine; | |
namespace MeshTools | |
{ | |
public class MeshPostProcessor : AssetPostprocessor | |
{ | |
private static string[] components = new string[] {"x", "y", "z", "w"}; | |
private void OnPostprocessModel(GameObject g) | |
{ | |
var deleteList = new List<GameObject>(); | |
Process(g.transform, deleteList); | |
foreach (var d in deleteList) | |
{ | |
Debug.Log("Deleting object " + d.name); | |
Object.DestroyImmediate(d); | |
} | |
} | |
private static void Process(Transform t, List<GameObject> deleteList) | |
{ | |
if (t.name.Contains("_DEL")) | |
{ | |
deleteList.Add(t.gameObject); | |
return; | |
} | |
if (t.name.Contains("_MERGE")) | |
{ | |
// get all mesh filters | |
var filters = t.GetComponentsInChildren<MeshFilter>(); | |
// get all meshes and transforms | |
var meshes = filters.Select(i => i.sharedMesh).ToArray(); | |
var transforms = filters.Select(i => i.transform).ToArray(); | |
if (meshes.Length != transforms.Length) | |
Debug.LogError("Mesh and transformation count mismatch when attempting to process " + t.name); | |
// generate CombineInstance array | |
var combines = new CombineInstance[meshes.Length]; | |
var mergedMesh = meshes[0]; | |
var newMesh = new Mesh(); | |
var baseMatrix = t.worldToLocalMatrix; | |
var material = filters[0].GetComponent<MeshRenderer>().sharedMaterial; | |
for (var i = 0; i < combines.Length; i++) | |
combines[i] = new CombineInstance | |
{ | |
mesh = meshes[i], | |
transform = baseMatrix * transforms[i].localToWorldMatrix | |
}; | |
// combine meshes into newMesh and copy data to mergedMesh | |
// we cant use newMesh because it will disappear once importing is done, | |
// also CombineMeshes doesnt include the base mesh in 2017.1 | |
newMesh.CombineMeshes(combines, true, true, false); | |
mergedMesh.vertices = newMesh.vertices; | |
mergedMesh.normals = newMesh.normals; | |
mergedMesh.triangles = newMesh.triangles; | |
mergedMesh.colors = newMesh.colors; | |
mergedMesh.boneWeights = newMesh.boneWeights; | |
mergedMesh.uv = newMesh.uv; | |
mergedMesh.RecalculateBounds(); | |
mergedMesh.RecalculateTangents(); | |
mergedMesh.name = t.name; | |
// clear any existing MeshFilter or MeshRenderer and delete other meshes | |
Object.DestroyImmediate(t.GetComponent<MeshFilter>()); | |
Object.DestroyImmediate(t.GetComponent<MeshRenderer>()); | |
for (var i = 1; i < combines.Length; i++) Object.DestroyImmediate(meshes[i]); | |
// assign mesh and material to this gameobject | |
var filter = t.gameObject.AddComponent<MeshFilter>(); | |
var renderer = t.gameObject.AddComponent<MeshRenderer>(); | |
filter.sharedMesh = mergedMesh; | |
renderer.sharedMaterial = material; | |
// add children to list for deletion at end of processing step | |
deleteList.AddRange(transforms.Select(i => i.gameObject)); | |
return; | |
} | |
if (t.name.Contains("_COLLIDER")) | |
{ | |
var filter = t.GetComponent<MeshFilter>(); | |
var renderer = t.GetComponent<MeshRenderer>(); | |
if (filter == null) Debug.LogWarning("Error processing " + t.name + ": no mesh filter available"); | |
var collider = t.gameObject.AddComponent<MeshCollider>(); | |
collider.sharedMesh = filter.sharedMesh; | |
collider.convex = true; | |
Object.DestroyImmediate(renderer); | |
Object.DestroyImmediate(filter); | |
} | |
if (t.name.Contains("_SPHERECOLLIDER")) | |
{ | |
var filter = t.GetComponent<MeshFilter>(); | |
var renderer = t.GetComponent<MeshRenderer>(); | |
if (filter == null) Debug.LogWarning("Error processing " + t.name + ": no mesh filter available"); | |
var aabb = filter.sharedMesh.bounds; | |
var collider = t.gameObject.AddComponent<SphereCollider>(); | |
collider.center = aabb.center; | |
collider.radius = (aabb.size.x + aabb.size.y + aabb.size.z) / 6; | |
Object.DestroyImmediate(renderer); | |
Object.DestroyImmediate(filter); | |
} | |
if (t.name.Contains("_CAPSULECOLLIDER")) | |
{ | |
var filter = t.GetComponent<MeshFilter>(); | |
var renderer = t.GetComponent<MeshRenderer>(); | |
if (filter == null) Debug.LogWarning("Error processing " + t.name + ": no mesh filter available"); | |
var aabb = filter.sharedMesh.bounds; | |
var size = aabb.size; | |
var collider = t.gameObject.AddComponent<CapsuleCollider>(); | |
collider.center = aabb.center; | |
if (size.x > size.y && size.x > size.z) | |
{ | |
collider.radius = (size.y + size.z) / 4; | |
collider.height = size.x; | |
collider.direction = 0; | |
} | |
else if (size.y > size.z && size.y > size.x) | |
{ | |
collider.radius = (size.x + size.z) / 4; | |
collider.height = size.y; | |
collider.direction = 1; | |
} | |
else | |
{ | |
collider.radius = (size.x + size.y) / 4; | |
collider.height = size.z; | |
collider.direction = 2; | |
} | |
Object.DestroyImmediate(renderer); | |
Object.DestroyImmediate(filter); | |
} | |
if (t.name.Contains("_BOXCOLLIDER")) | |
{ | |
var filter = t.GetComponent<MeshFilter>(); | |
var renderer = t.GetComponent<MeshRenderer>(); | |
if (filter == null) Debug.LogWarning("Error processing " + t.name + ": no mesh filter available"); | |
var aabb = filter.sharedMesh.bounds; | |
var collider = t.gameObject.AddComponent<BoxCollider>(); | |
collider.center = aabb.center; | |
collider.size = aabb.size; | |
Object.DestroyImmediate(renderer); | |
Object.DestroyImmediate(filter); | |
} | |
foreach (Transform child in t) Process(child, deleteList); | |
var anim = t.GetComponent<Animation>(); | |
if (anim != null) | |
{ | |
foreach (var state in anim) | |
{ | |
var clip = ((AnimationState) state).clip; | |
Debug.Log("Trimming animation " + clip.name); | |
TrimAnimation(clip, t, deleteList); | |
} | |
} | |
} | |
private static void TrimAnimation(AnimationClip clip, Transform t, List<GameObject> deleteList) | |
{ | |
var bindings = AnimationUtility.GetCurveBindings(clip); | |
foreach (EditorCurveBinding b in bindings) | |
{ | |
var curve = AnimationUtility.GetEditorCurve(clip, b); | |
var target = (Transform) AnimationUtility.GetAnimatedObject(t.gameObject, b); | |
if (curve.length > 2) continue; | |
if (curve.length == 2 && !deleteList.Contains(target.gameObject)) | |
{ | |
continue; | |
//if (!Mathf.Approximately(curve[0].value, curve[1].value)) continue; | |
//if (!Mathf.Approximately(curve[0].value, 0.0f) && !Mathf.Approximately(curve[0].value, 1.0f)) continue; | |
} | |
AnimationUtility.SetEditorCurve(clip, b, null); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment