您最多选择25个主题 主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

157 行
6.6 KiB

using System;
using System.Collections.Generic;
using System.Linq;
using UniGLTF;
using UniGLTF.M17N;
using UnityEditor;
using UnityEngine;
namespace MetaCity.BundleKit.Editor.VRM
{
[Serializable]
public class MetaCityMeshExportValidator : ScriptableObject
{
public static Mesh GetMesh(Renderer r)
{
if (r is SkinnedMeshRenderer smr)
{
return smr.sharedMesh;
}
if (r is MeshRenderer)
{
MeshFilter f = r.GetComponent<MeshFilter>();
if (f != null)
{
return f.sharedMesh;
}
}
return null;
}
public MeshExportList Meshes = new MeshExportList();
public int ExpectedExportByteSize => Meshes.Where(x => x.IsRendererActive).Sum(x => x.ExportByteSize);
public void SetRoot(GameObject ExportRoot, GltfExportSettings settings, IBlendShapeExportFilter blendShapeFilter)
{
if (ExportRoot == null)
{
return;
}
Meshes.GetInfo(ExportRoot.transform.Traverse().Skip(1), settings);
foreach (var info in Meshes)
{
info.CalcMeshSize(ExportRoot, info.Renderers[0].Item1, settings, blendShapeFilter);
}
}
public IMaterialValidator MaterialValidator = new DefaultMaterialValidator();
public enum Messages
{
[LangMsg(Languages.en, "Materials with fewer sub-meshes")]
[LangMsg(Languages.ja, "サブメッシュ数より少ないマテリアル")]
MATERIALS_LESS_THAN_SUBMESH_COUNT,
[LangMsg(Languages.en, "Materials with more sub-meshes")]
[LangMsg(Languages.ja, "サブメッシュ数より多いマテリアル")]
MATERIALS_GREATER_THAN_SUBMESH_COUNT,
[LangMsg(Languages.en, "Renderer has null in material")]
[LangMsg(Languages.ja, "レンダラーの material に null があります")]
MATERIALS_CONTAINS_NULL,
[LangMsg(Languages.en, "A Shader that cannot be exported")]
[LangMsg(Languages.ja, "エクスポート非対応のシェーダーです")]
UNKNOWN_SHADER,
[LangMsg(Languages.en, "Meshes containing BlendShapes with multiple Frames cannot be exported")]
[LangMsg(Languages.ja, "複数Frameを持つBlendShapeを含むMeshはエクスポートできません")]
MULTIFRAME_BLENDSHAPE,
}
internal Func<bool> UseCustomShaderGetter;
public IEnumerable<Validation> Validate(GameObject ExportRoot)
{
foreach (var info in Meshes)
{
// invalid materials.len
if (info.Materials.Length < info.Mesh.subMeshCount)
{
// submesh より material の方が少ない
yield return Validation.Error(Messages.MATERIALS_LESS_THAN_SUBMESH_COUNT.Msg());
}
else
{
if (info.Materials.Length > info.Mesh.subMeshCount)
{
// submesh より material の方が多い
yield return Validation.Warning(Messages.MATERIALS_GREATER_THAN_SUBMESH_COUNT.Msg());
}
if (info.Materials.Take(info.Mesh.subMeshCount).Any(x => x == null))
{
// material に null が含まれる(unity で magenta になっているはず)
yield return Validation.Error(Messages.MATERIALS_CONTAINS_NULL.Msg(), ValidationContext.Create(info.Renderers[0].Item1));
}
}
// blendShapeFrame
var shapeCount = info.Mesh.blendShapeCount;
var multiFrameShapes = new List<string>();
for (int i = 0; i < shapeCount; ++i)
{
if (info.Mesh.GetBlendShapeFrameCount(i) > 1)
{
multiFrameShapes.Add($"[{i}]({info.Mesh.GetBlendShapeName(i)})");
}
}
if (multiFrameShapes.Count > 0)
{
var names = String.Join(", ", multiFrameShapes);
yield return Validation.Error($"{names}: {Messages.MULTIFRAME_BLENDSHAPE.Msg()}", ValidationContext.Create(info.Renderers[0].Item1));
}
}
foreach (var m in Meshes.GetUniqueMaterials())
{
var gltfMaterial = MaterialValidator.GetGltfMaterialTypeFromUnityShaderName(m.shader.name);
if (string.IsNullOrEmpty(gltfMaterial)&&!UseCustomShaderGetter.Invoke())
{
yield return Validation.Warning($"{m}: unknown shader: {m.shader.name} => Should Use Custom Shader", ValidationContext.Create(m));
}
var used = new HashSet<Texture>();
foreach (var (propName, texture) in MaterialValidator.EnumerateTextureProperties(m))
{
if (texture == null)
{
continue;
}
var assetPath = AssetDatabase.GetAssetPath(texture);
if (!string.IsNullOrEmpty(assetPath))
{
if (AssetImporter.GetAtPath(assetPath) is TextureImporter textureImporter)
{
switch (textureImporter.textureType)
{
case TextureImporterType.Default:
case TextureImporterType.NormalMap:
break;
default:
// EditorTextureSerializer throw Exception
// エクスポート未実装
if (used.Add(texture))
{
yield return Validation.Error($"{texture}: unknown texture type: {textureImporter.textureType}", ValidationContext.Create(texture));
}
break;
}
}
}
}
yield break;
}
}
}
}