175 lines
5.1 KiB
C#
175 lines
5.1 KiB
C#
using System.Collections;
|
||||
|
|
using System.Collections.Generic;
|
|||
|
|
using UnityEngine;
|
|||
|
|
using UnityEditor;
|
|||
|
|
using System.IO;
|
|||
|
|
|
|||
|
|
public class AnimMapBakerWindow : EditorWindow {
|
|||
|
|
|
|||
|
|
private enum SaveStrategy
|
|||
|
|
{
|
|||
|
|
AnimMap,//only anim map
|
|||
|
|
Mat,//with shader
|
|||
|
|
Prefab//prefab with mat
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#region 字段
|
|||
|
|
|
|||
|
|
public static GameObject targetGo;
|
|||
|
|
private static AnimMapBaker baker;
|
|||
|
|
private static string path = "GamePlay_ECS\\EntityConvert";
|
|||
|
|
|
|||
|
|
private static string subPath = "SubPath";
|
|||
|
|
private static SaveStrategy stratege = SaveStrategy.AnimMap;
|
|||
|
|
private static Shader _animMapShader;
|
|||
|
|
|
|||
|
|
private static Shader animMapShader
|
|||
|
|
{
|
|||
|
|
get
|
|||
|
|
{
|
|||
|
|
if(_animMapShader == null)
|
|||
|
|
_animMapShader = Shader.Find(animMapShaderName);
|
|||
|
|
return _animMapShader;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
private static string animMapShaderName = "ECSGame/URP/UnlitAnim";
|
|||
|
|
#endregion
|
|||
|
|
|
|||
|
|
|
|||
|
|
#region 方法
|
|||
|
|
|
|||
|
|
[MenuItem("Tools/AnimMapBaker")]
|
|||
|
|
public static void ShowWindow()
|
|||
|
|
{
|
|||
|
|
EditorWindow.GetWindow(typeof(AnimMapBakerWindow));
|
|||
|
|
baker = new AnimMapBaker();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void OnGUI()
|
|||
|
|
{
|
|||
|
|
targetGo = (GameObject)EditorGUILayout.ObjectField(targetGo, typeof(GameObject), true);
|
|||
|
|
subPath = targetGo == null ? subPath : targetGo.name;
|
|||
|
|
EditorGUILayout.LabelField(string.Format("保存路径output path:{0}", Path.Combine(path, subPath)));
|
|||
|
|
path = EditorGUILayout.TextField(path);
|
|||
|
|
subPath = EditorGUILayout.TextField(subPath);
|
|||
|
|
stratege = (SaveStrategy)EditorGUILayout.EnumPopup("保存策略output type:", stratege);
|
|||
|
|
if (GUILayout.Button("Bake"))
|
|||
|
|
{
|
|||
|
|
if(targetGo == null)
|
|||
|
|
{
|
|||
|
|
EditorUtility.DisplayDialog("err", "targetGo is null!", "OK");
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if(baker == null)
|
|||
|
|
{
|
|||
|
|
baker = new AnimMapBaker();
|
|||
|
|
}
|
|||
|
|
baker.SetAnimData(targetGo);
|
|||
|
|
List<BakedData> list =baker.Bake();
|
|||
|
|
if (list != null)
|
|||
|
|
{
|
|||
|
|
for(int i = 0; i < list.Count; i++)
|
|||
|
|
{
|
|||
|
|
BakedData data = list[i];
|
|||
|
|
Save(ref data);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
private void Save(ref BakedData data)
|
|||
|
|
{
|
|||
|
|
switch(stratege)
|
|||
|
|
{
|
|||
|
|
case SaveStrategy.AnimMap:
|
|||
|
|
SaveAsAsset(ref data);
|
|||
|
|
break;
|
|||
|
|
case SaveStrategy.Mat:
|
|||
|
|
SaveAsMat(ref data);
|
|||
|
|
break;
|
|||
|
|
case SaveStrategy.Prefab:
|
|||
|
|
SaveAsPrefab(ref data);
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
AssetDatabase.SaveAssets();
|
|||
|
|
AssetDatabase.Refresh();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private Texture2D SaveAsAsset(ref BakedData data)
|
|||
|
|
{
|
|||
|
|
string folderPath = CreateFolder();
|
|||
|
|
Texture2D animMap = new Texture2D(data.animMapWidth, data.animMapHeight, TextureFormat.RGBAHalf, false);
|
|||
|
|
animMap.LoadRawTextureData(data.rawAnimMap);
|
|||
|
|
AssetDatabase.CreateAsset(animMap, Path.Combine(folderPath, GetValidName(data.name) + ".asset"));
|
|||
|
|
return animMap;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public static string GetValidName(string pName)
|
|||
|
|
{
|
|||
|
|
pName = pName.Replace("|", "@");
|
|||
|
|
return pName;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private Material SaveAsMat(ref BakedData data)
|
|||
|
|
{
|
|||
|
|
if(animMapShader == null)
|
|||
|
|
{
|
|||
|
|
EditorUtility.DisplayDialog("err", "shader is null!!", "OK");
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if(targetGo == null || !targetGo.GetComponentInChildren<SkinnedMeshRenderer>())
|
|||
|
|
{
|
|||
|
|
EditorUtility.DisplayDialog("err", "SkinnedMeshRender is null!!", "OK");
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
SkinnedMeshRenderer smr = targetGo.GetComponentInChildren<SkinnedMeshRenderer>();
|
|||
|
|
Material mat = new Material(animMapShader);
|
|||
|
|
Texture2D animMap = SaveAsAsset(ref data);
|
|||
|
|
mat.SetTexture("_MainTex", smr.sharedMaterial.mainTexture);
|
|||
|
|
mat.SetTexture("_AnimMap", animMap);
|
|||
|
|
mat.SetFloat("_AnimLen", data.animLen);
|
|||
|
|
|
|||
|
|
string folderPath = CreateFolder();
|
|||
|
|
AssetDatabase.CreateAsset(mat, Path.Combine(folderPath, GetValidName(data.name) + ".mat"));
|
|||
|
|
|
|||
|
|
return mat;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void SaveAsPrefab(ref BakedData data)
|
|||
|
|
{
|
|||
|
|
Material mat = SaveAsMat(ref data);
|
|||
|
|
|
|||
|
|
if(mat == null)
|
|||
|
|
{
|
|||
|
|
EditorUtility.DisplayDialog("err", "mat is null!!", "OK");
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
GameObject go = new GameObject();
|
|||
|
|
go.AddComponent<MeshRenderer>().sharedMaterial = mat;
|
|||
|
|
go.AddComponent<MeshFilter>().sharedMesh = targetGo.GetComponentInChildren<SkinnedMeshRenderer>().sharedMesh;
|
|||
|
|
|
|||
|
|
string folderPath = CreateFolder();
|
|||
|
|
PrefabUtility.CreatePrefab(Path.Combine(folderPath, GetValidName(data.name) + ".prefab").Replace("\\", "/"), go);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private string CreateFolder()
|
|||
|
|
{
|
|||
|
|
string folderPath = Path.Combine("Assets/" + path, subPath);
|
|||
|
|
if (!AssetDatabase.IsValidFolder(folderPath))
|
|||
|
|
{
|
|||
|
|
AssetDatabase.CreateFolder("Assets/" + path, subPath);
|
|||
|
|
}
|
|||
|
|
return folderPath;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#endregion
|
|||
|
|
|
|||
|
|
|
|||
|
|
}
|