Files
2025-01-07 18:54:46 +02:00

248 lines
9.0 KiB
C#

using System.Collections.Generic;
using UMA;
using Unity.Collections;
using UnityEditor;
using UnityEngine;
public class SlotToMesh : EditorWindow
{
[Tooltip("The SlotDataAsset that you want to convert")]
public SlotDataAsset baseObject;
[Tooltip("The folder where the Mesh will be created")]
public UnityEngine.Object slotFolder;
[MenuItem("UMA/Slot To Mesh", priority = 20)]
public static void OpenSlotToMeshWindow()
{
SlotToMesh window = (SlotToMesh)EditorWindow.GetWindow(typeof(SlotToMesh));
window.titleContent.text = "UMA Slot To Mesh";
}
public string GetFolder(ref UnityEngine.Object folderObject)
{
if (folderObject != null)
{
string destpath = AssetDatabase.GetAssetPath(folderObject);
if (string.IsNullOrEmpty(destpath))
{
folderObject = null;
}
else if (!System.IO.Directory.Exists(destpath))
{
destpath = destpath.Substring(0, destpath.LastIndexOf('/'));
}
return destpath;
}
return null;
}
void OnGUI()
{
EditorGUILayout.LabelField("UMA Slot To Mesh", EditorStyles.boldLabel);
EditorGUILayout.HelpBox("This will convert an UMA slot into a Mesh. Once converted, it can be then be saved as an FBX using unity tools", MessageType.None, false);
baseObject = (SlotDataAsset)EditorGUILayout.ObjectField("Slot Data Asset", baseObject, typeof(SlotDataAsset), true);
slotFolder = EditorGUILayout.ObjectField("Dest Folder", slotFolder, typeof(UnityEngine.Object), false) as UnityEngine.Object;
string folder = GetFolder(ref slotFolder);
if (slotFolder != null && baseObject != null)
{
if (GUILayout.Button("Make Mesh") && slotFolder != null)
{
Mesh mesh = ConvertSlotToMesh(baseObject);
string meshName = folder + "/" + baseObject.slotName + "_Mesh.asset";
string goName = folder + "/" + baseObject.slotName + "_Go.prefab";
// Save Mesh to disk.
// smr.sharedMesh.Optimize(); This blows up some versions of Unity.
//CustomAssetUtility.SaveAsset<Mesh>(mesh, meshName);
AssetDatabase.CreateAsset(mesh, meshName);
GameObject go = new GameObject(baseObject.slotName);
go.hideFlags = HideFlags.DontSaveInEditor;
MeshFilter mf = go.AddComponent<MeshFilter>();
mf.mesh = mesh;
MeshRenderer mr = go.AddComponent<MeshRenderer>();
mr.materials = new Material[mesh.subMeshCount];
for (int i = 0; i < mesh.subMeshCount; i++)
{
mr.materials[i] = AssetDatabase.GetBuiltinExtraResource<Material>("Default-Diffuse.mat");
}
PrefabUtility.SaveAsPrefabAsset(go, goName);
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
EditorUtility.DisplayDialog("UMA Prefab Saver", "Conversion complete", "OK");
}
}
else
{
if (baseObject == null)
{
EditorGUILayout.HelpBox("A valid SlotDataAsset must be supplied", MessageType.Error);
}
if (slotFolder == null)
{
EditorGUILayout.HelpBox("A valid base folder must be supplied", MessageType.Error);
}
}
}
public static BoneWeight[] ConvertBoneweight1(BoneWeight1[] weights, byte[] bonesPerVertex)
{
List<BoneWeight> bones = new List<BoneWeight>();
int boneIndex = 0;
for(int i=0;i < bonesPerVertex.Length; i++)
{
int bonecount = bonesPerVertex[boneIndex];
BoneWeight bw = new BoneWeight();
for (int j = 0; j < bonecount; j++)
{
if (j == 0)
{
bw.boneIndex0 = weights[boneIndex].boneIndex;
bw.weight0 = weights[boneIndex].weight;
}
if (j == 1)
{
bw.boneIndex1 = weights[boneIndex].boneIndex;
bw.weight1 = weights[boneIndex].weight;
}
if (j == 2)
{
bw.boneIndex2 = weights[boneIndex].boneIndex;
bw.weight2 = weights[boneIndex].weight;
}
if (j == 3)
{
bw.boneIndex3 = weights[boneIndex].boneIndex;
bw.weight3 = weights[boneIndex].weight;
}
boneIndex ++;
}
}
return bones.ToArray();
}
public static BoneWeight[] ConvertBoneweights(UMABoneWeight[] umaBones)
{
BoneWeight[] boneWeights = new BoneWeight[umaBones.Length];
for (int i = 0; i < umaBones.Length; i++)
{
boneWeights[i].boneIndex0 = umaBones[i].boneIndex0;
boneWeights[i].boneIndex1 = umaBones[i].boneIndex1;
boneWeights[i].boneIndex2 = umaBones[i].boneIndex2;
boneWeights[i].boneIndex3 = umaBones[i].boneIndex3;
boneWeights[i].weight0 = umaBones[i].weight0;
boneWeights[i].weight1 = umaBones[i].weight1;
boneWeights[i].weight2 = umaBones[i].weight2;
boneWeights[i].weight3 = umaBones[i].weight3;
}
return boneWeights;
}
public static Mesh ConvertSlotToMesh(SlotDataAsset slot)
{
Mesh mesh = new Mesh();
mesh.vertices = slot.meshData.vertices;
mesh.uv = slot.meshData.uv;
mesh.normals = slot.meshData.normals;
mesh.tangents = slot.meshData.tangents;
mesh.subMeshCount = slot.meshData.subMeshCount;
/*
if (slot.meshData.boneWeights != null && slot.meshData.boneWeights.Length > 0)
{
mesh.boneWeights = ConvertBoneweights(slot.meshData.boneWeights);
}
else
{
mesh.boneWeights = ConvertBoneweight1(slot.meshData.ManagedBoneWeights, slot.meshData.ManagedBonesPerVertex);
var unityBonesPerVertex = new NativeArray<byte>(slot.meshData.ManagedBonesPerVertex, Allocator.Temp);
var unityBoneWeights = new NativeArray<BoneWeight1>(slot.meshData.ManagedBoneWeights, Allocator.Temp);
mesh.SetBoneWeights(unityBonesPerVertex,unityBoneWeights);
} */
for (int i = 0; i < slot.meshData.subMeshCount; i++)
{
var tris = GetTriangles(slot.meshData, i);
mesh.subMeshCount = slot.meshData.subMeshCount;
mesh.SetIndices(tris, MeshTopology.Triangles, i);
}
return mesh;
}
public static Mesh ConvertSlotToMesh(SlotDataAsset slot, Quaternion Rotation, int VertexHighlight)
{
Mesh mesh = new Mesh();
mesh.vertices = slot.meshData.vertices;
mesh.uv = slot.meshData.uv;
mesh.normals = slot.meshData.normals;
mesh.tangents = slot.meshData.tangents;
mesh.subMeshCount = slot.meshData.subMeshCount;
Matrix4x4 rot = Matrix4x4.TRS(Vector3.zero, Rotation, Vector3.one);
for (int i = 0; i < slot.meshData.subMeshCount; i++)
{
var tris = GetTriangles(slot.meshData, i);
mesh.subMeshCount = slot.meshData.subMeshCount;
mesh.SetIndices(tris, MeshTopology.Triangles, i);
}
if (VertexHighlight != -1)
{
if (VertexHighlight >= mesh.vertices.Length)
{
VertexHighlight = mesh.vertices.Length - 1;
}
Vector3 pos = mesh.vertices[VertexHighlight];
GameObject throwAway = GameObject.CreatePrimitive(PrimitiveType.Sphere);
Mesh sphereMesh = throwAway.GetComponent<MeshFilter>().sharedMesh;
Mesh Sphere = Object.Instantiate(sphereMesh);
Vector3[] vertices = Sphere.vertices;
for (int i = 0; i < vertices.Length; i++)
{
vertices[i] = pos+(vertices[i] * 0.005f);
}
Sphere.vertices = vertices;
Mesh combinedMesh = new Mesh();
CombineInstance[] combine = new CombineInstance[2];
combine[0].mesh = mesh;
combine[0].transform = rot;
combine[1].mesh = Sphere;
combine[1].transform = rot;
combinedMesh.CombineMeshes(combine, false, true, false);
GameObject.DestroyImmediate(throwAway);
DestroyImmediate(mesh);
return combinedMesh;
}
else
{
CombineInstance[] combineInstances = new CombineInstance[1];
combineInstances[0].mesh = mesh;
combineInstances[0].transform = rot;
Mesh combinedMesh = new Mesh();
combinedMesh.CombineMeshes(combineInstances, false, true, false);
DestroyImmediate(mesh);
return combinedMesh;
}
}
public static int[] GetTriangles(UMAMeshData meshData, int subMesh)
{
return meshData.submeshes[subMesh].getBaseTriangles();
}
}