216 lines
8.0 KiB
C#
216 lines
8.0 KiB
C#
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using System.Text.RegularExpressions;
|
|
using UnityEditor;
|
|
using UnityEngine;
|
|
|
|
namespace KSPTools
|
|
{
|
|
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)
|
|
{
|
|
var regex = new Regex(@"\.[0-9][0-9][0-9]");
|
|
var name = t.name;
|
|
t.name = regex.Replace(name, "");
|
|
|
|
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;
|
|
}
|
|
|
|
AnimationUtility.SetEditorCurve(clip, b, null);
|
|
}
|
|
}
|
|
}
|
|
} |