WIP 構成変更中。validation 一時停止。

This commit is contained in:
ousttrue
2020-08-07 19:29:57 +09:00
parent f9c240476f
commit 501eb6edd0
6 changed files with 294 additions and 291 deletions

View File

@@ -16,12 +16,12 @@ namespace VRM
/// </summary>
/// <param name="path">出力先</param>
/// <param name="settings">エクスポート設定</param>
public static void Export(string path, VRMExportSettings settings)
public static void Export(string path, GameObject exportRoot, VRMExportSettings settings)
{
List<GameObject> destroy = new List<GameObject>();
try
{
Export(path, settings, destroy);
Export(path, exportRoot, settings, destroy);
}
finally
{
@@ -136,9 +136,9 @@ namespace VRM
/// <param name="path"></param>
/// <param name="settings"></param>
/// <param name="destroy">作業が終わったらDestoryするべき一時オブジェクト</param>
static void Export(string path, VRMExportSettings settings, List<GameObject> destroy)
static void Export(string path, GameObject exportRoot, VRMExportSettings settings, List<GameObject> destroy)
{
var target = settings.Source;
var target = exportRoot;
// 常にコピーする。シーンを変化させない
target = GameObject.Instantiate(target);
@@ -146,8 +146,8 @@ namespace VRM
{
// copy元
var animator = settings.Source.GetComponent<Animator>();
var beforeTransforms = settings.Source.GetComponentsInChildren<Transform>();
var animator = exportRoot.GetComponent<Animator>();
var beforeTransforms = exportRoot.GetComponentsInChildren<Transform>();
// copy先
var afterTransforms = target.GetComponentsInChildren<Transform>();
// copy先のhumanoidBoneのリストを得る

View File

@@ -8,40 +8,8 @@ using UnityEngine;
namespace VRM
{
[Serializable]
public class VRMExportSettings
public class VRMExportSettings : ScriptableObject
{
/// <summary>
/// エクスポート対象
/// </summary>
public GameObject Source;
// #region Meta
// /// <summary>
// /// エクスポート名
// /// </summary>
// public string Title;
// /// <summary>
// /// エクスポートバージョン(エクスポートするModelのバージョン)
// /// </summary>
// public string Version;
// /// <summary>
// /// 作者
// /// </summary>
// public string Author;
// /// <summary>
// /// 作者連絡先
// /// </summary>
// public string ContactInformation;
// /// <summary>
// /// 作品引用
// /// </summary>
// public string Reference;
// #endregion
#region Settings
/// <summary>
/// エクスポート時に強制的にT-Pose化する
@@ -97,216 +65,212 @@ namespace VRM
return fileName.Length > 64;
}
// /// <summary>
// /// ボーン名の重複を確認
// /// </summary>
// /// <returns></returns>
// bool DuplicateBoneNameExists()
// {
// var bones = ExportRoot.transform.Traverse().ToArray();
// var duplicates = bones
// .GroupBy(p => p.name)
// .Where(g => g.Count() > 1)
// .Select(g => g.Key);
/// <summary>
/// ボーン名の重複を確認
/// </summary>
/// <returns></returns>
bool DuplicateBoneNameExists()
{
var bones = Source.transform.Traverse().ToArray();
var duplicates = bones
.GroupBy(p => p.name)
.Where(g => g.Count() > 1)
.Select(g => g.Key);
// return (duplicates.Any());
// }
return (duplicates.Any());
}
// /// <summary>
// /// エクスポート可能か検証する
// /// </summary>
// /// <returns></returns>
// public IEnumerable<Validation> Validate()
// {
// if (ExportRoot == null)
// {
// yield return Validation.Error("Require source");
// yield break;
// }
/// <summary>
/// エクスポート可能か検証する
/// </summary>
/// <returns></returns>
public IEnumerable<Validation> Validate()
{
if (Source == null)
{
yield return Validation.Error("Require source");
yield break;
}
// if (ExportRoot.transform.position != Vector3.zero ||
// ExportRoot.transform.rotation != Quaternion.identity ||
// ExportRoot.transform.localScale != Vector3.one)
// {
// // EditorUtility.DisplayDialog("Error", "The Root transform should have Default translation, rotation and scale.", "ok");
// yield return Validation.Warning("The Root translation, rotation and scale will be dropped.");
// }
if (Source.transform.position != Vector3.zero ||
Source.transform.rotation != Quaternion.identity ||
Source.transform.localScale != Vector3.one)
{
// EditorUtility.DisplayDialog("Error", "The Root transform should have Default translation, rotation and scale.", "ok");
yield return Validation.Warning("The Root translation, rotation and scale will be dropped.");
}
// var animator = ExportRoot.GetComponent<Animator>();
// if (animator == null)
// {
// yield return Validation.Error("Require animator. ");
// }
// else
// {
// if (animator.avatar == null)
// {
// yield return Validation.Error("Require animator.avatar. ");
// }
// else if (!animator.avatar.isValid)
// {
// yield return Validation.Error("Animator.avatar is not valid. ");
// }
// else if (!animator.avatar.isHuman)
// {
// yield return Validation.Error("Animator.avatar is not humanoid. Please change model's AnimationType to humanoid. ");
// }
var animator = Source.GetComponent<Animator>();
if (animator == null)
{
yield return Validation.Error("Require animator. ");
}
else
{
if (animator.avatar == null)
{
yield return Validation.Error("Require animator.avatar. ");
}
else if (!animator.avatar.isValid)
{
yield return Validation.Error("Animator.avatar is not valid. ");
}
else if (!animator.avatar.isHuman)
{
yield return Validation.Error("Animator.avatar is not humanoid. Please change model's AnimationType to humanoid. ");
}
// var jaw = animator.GetBoneTransform(HumanBodyBones.Jaw);
// if (jaw != null)
// {
// yield return Validation.Warning("Jaw bone is included. It may not be what you intended. Please check the humanoid avatar setting screen");
// }
// }
var jaw = animator.GetBoneTransform(HumanBodyBones.Jaw);
if (jaw != null)
{
yield return Validation.Warning("Jaw bone is included. It may not be what you intended. Please check the humanoid avatar setting screen");
}
}
// if (DuplicateBoneNameExists())
// {
// yield return Validation.Warning("There is a bone with the same name in the hierarchy. If exported, these bones will be automatically renamed.");
// }
if (DuplicateBoneNameExists())
{
yield return Validation.Warning("There is a bone with the same name in the hierarchy. If exported, these bones will be automatically renamed.");
}
// if (ReduceBlendshape && ExportRoot.GetComponent<VRMBlendShapeProxy>() == null)
// {
// yield return Validation.Error("ReduceBlendshapeSize needs VRMBlendShapeProxy. You need to convert to VRM once.");
// }
if (ReduceBlendshape && Source.GetComponent<VRMBlendShapeProxy>() == null)
{
yield return Validation.Error("ReduceBlendshapeSize needs VRMBlendShapeProxy. You need to convert to VRM once.");
}
// var vertexColor = ExportRoot.GetComponentsInChildren<SkinnedMeshRenderer>().Any(x => x.sharedMesh.colors.Length > 0);
// if (vertexColor)
// {
// yield return Validation.Warning("This model contains vertex color");
// }
var vertexColor = Source.GetComponentsInChildren<SkinnedMeshRenderer>().Any(x => x.sharedMesh.colors.Length > 0);
if (vertexColor)
{
yield return Validation.Warning("This model contains vertex color");
}
// var renderers = ExportRoot.GetComponentsInChildren<Renderer>();
// if (renderers.All(x => !x.gameObject.activeInHierarchy))
// {
// yield return Validation.Error("No active mesh");
// }
var renderers = Source.GetComponentsInChildren<Renderer>();
if (renderers.All(x => !x.gameObject.activeInHierarchy))
{
yield return Validation.Error("No active mesh");
}
// var materials = renderers.SelectMany(x => x.sharedMaterials).Distinct();
// foreach (var material in materials)
// {
// if (material.shader.name == "Standard")
// {
// // standard
// continue;
// }
var materials = renderers.SelectMany(x => x.sharedMaterials).Distinct();
foreach (var material in materials)
{
if (material.shader.name == "Standard")
{
// standard
continue;
}
// if (VRMMaterialExporter.UseUnlit(material.shader.name))
// {
// // unlit
// continue;
// }
if (VRMMaterialExporter.UseUnlit(material.shader.name))
{
// unlit
continue;
}
// if (VRMMaterialExporter.VRMExtensionShaders.Contains(material.shader.name))
// {
// // VRM supported
// continue;
// }
if (VRMMaterialExporter.VRMExtensionShaders.Contains(material.shader.name))
{
// VRM supported
continue;
}
// yield return Validation.Warning(string.Format("{0}: unknown shader '{1}' is used. this will export as `Standard` fallback",
// material.name,
// material.shader.name));
// }
yield return Validation.Warning(string.Format("{0}: unknown shader '{1}' is used. this will export as `Standard` fallback",
material.name,
material.shader.name));
}
// foreach (var material in materials)
// {
// if (IsFileNameLengthTooLong(material.name))
// yield return Validation.Error(string.Format("FileName '{0}' is too long. ", material.name));
// }
foreach (var material in materials)
{
if (IsFileNameLengthTooLong(material.name))
yield return Validation.Error(string.Format("FileName '{0}' is too long. ", material.name));
}
// var textureNameList = new List<string>();
// foreach (var material in materials)
// {
// var shader = material.shader;
// int propertyCount = ShaderUtil.GetPropertyCount(shader);
// for (int i = 0; i < propertyCount; i++)
// {
// if (ShaderUtil.GetPropertyType(shader, i) == ShaderUtil.ShaderPropertyType.TexEnv)
// {
// if ((material.GetTexture(ShaderUtil.GetPropertyName(shader, i)) != null))
// {
// var textureName = material.GetTexture(ShaderUtil.GetPropertyName(shader, i)).name;
// if (!textureNameList.Contains(textureName))
// textureNameList.Add(textureName);
// }
// }
// }
// }
var textureNameList = new List<string>();
foreach (var material in materials)
{
var shader = material.shader;
int propertyCount = ShaderUtil.GetPropertyCount(shader);
for (int i = 0; i < propertyCount; i++)
{
if (ShaderUtil.GetPropertyType(shader, i) == ShaderUtil.ShaderPropertyType.TexEnv)
{
if ((material.GetTexture(ShaderUtil.GetPropertyName(shader, i)) != null))
{
var textureName = material.GetTexture(ShaderUtil.GetPropertyName(shader, i)).name;
if (!textureNameList.Contains(textureName))
textureNameList.Add(textureName);
}
}
}
}
// foreach (var textureName in textureNameList)
// {
// if (IsFileNameLengthTooLong(textureName))
// yield return Validation.Error(string.Format("FileName '{0}' is too long. ", textureName));
// }
foreach (var textureName in textureNameList)
{
if (IsFileNameLengthTooLong(textureName))
yield return Validation.Error(string.Format("FileName '{0}' is too long. ", textureName));
}
// var vrmMeta = ExportRoot.GetComponent<VRMMeta>();
// if (vrmMeta != null && vrmMeta.Meta != null && vrmMeta.Meta.Thumbnail != null)
// {
// var thumbnailName = vrmMeta.Meta.Thumbnail.name;
// if (IsFileNameLengthTooLong(thumbnailName))
// yield return Validation.Error(string.Format("FileName '{0}' is too long. ", thumbnailName));
// }
var vrmMeta = Source.GetComponent<VRMMeta>();
if (vrmMeta != null && vrmMeta.Meta != null && vrmMeta.Meta.Thumbnail != null)
{
var thumbnailName = vrmMeta.Meta.Thumbnail.name;
if (IsFileNameLengthTooLong(thumbnailName))
yield return Validation.Error(string.Format("FileName '{0}' is too long. ", thumbnailName));
}
// var meshFilters = ExportRoot.GetComponentsInChildren<MeshFilter>();
// var meshesName = meshFilters.Select(x => x.sharedMesh.name).Distinct();
// foreach (var meshName in meshesName)
// {
// if (IsFileNameLengthTooLong(meshName))
// yield return Validation.Error(string.Format("FileName '{0}' is too long. ", meshName));
// }
var meshFilters = Source.GetComponentsInChildren<MeshFilter>();
var meshesName = meshFilters.Select(x => x.sharedMesh.name).Distinct();
foreach (var meshName in meshesName)
{
if (IsFileNameLengthTooLong(meshName))
yield return Validation.Error(string.Format("FileName '{0}' is too long. ", meshName));
}
// var skinnedmeshRenderers = ExportRoot.GetComponentsInChildren<SkinnedMeshRenderer>();
// var skinnedmeshesName = skinnedmeshRenderers.Select(x => x.sharedMesh.name).Distinct();
// foreach (var skinnedmeshName in skinnedmeshesName)
// {
// if (IsFileNameLengthTooLong(skinnedmeshName))
// yield return Validation.Error(string.Format("FileName '{0}' is too long. ", skinnedmeshName));
// }
// }
var skinnedmeshRenderers = Source.GetComponentsInChildren<SkinnedMeshRenderer>();
var skinnedmeshesName = skinnedmeshRenderers.Select(x => x.sharedMesh.name).Distinct();
foreach (var skinnedmeshName in skinnedmeshesName)
{
if (IsFileNameLengthTooLong(skinnedmeshName))
yield return Validation.Error(string.Format("FileName '{0}' is too long. ", skinnedmeshName));
}
}
// /// <summary>
// /// 対象のモデルからMeta情報を取得し、エクスポート設定を初期する
// /// </summary>
// /// <param name="go"></param>
// public void InitializeFrom(GameObject go)
// {
// //
// // initialize
// //
// // var desc = ExportRoot == null ? null : go.GetComponent<VRMHumanoidDescription>();
// // if (desc == null)
// // {
// // // 初回のVRMエクスポートとみなす
// // ForceTPose = false; // option
// // PoseFreeze = true;
// // }
// // else
// // {
// // // すでに正規化済みとみなす
// // ForceTPose = false;
// // PoseFreeze = false;
// // }
/// <summary>
/// 対象のモデルからMeta情報を取得し、エクスポート設定を初期する
/// </summary>
/// <param name="go"></param>
public void InitializeFrom(GameObject go)
{
if (Source == go) return;
Source = go;
//
// initialize
//
var desc = Source == null ? null : go.GetComponent<VRMHumanoidDescription>();
if (desc == null)
{
// 初回のVRMエクスポートとみなす
ForceTPose = false; // option
PoseFreeze = true;
}
else
{
// すでに正規化済みとみなす
ForceTPose = false;
PoseFreeze = false;
}
//
// Meta
//
var meta = Source == null ? null : go.GetComponent<VRMMeta>();
// if (meta != null && meta.Meta != null)
// {
// Title = meta.Meta.Title;
// Version = string.IsNullOrEmpty(meta.Meta.Version) ? "0.0" : meta.Meta.Version;
// Author = meta.Meta.Author;
// ContactInformation = meta.Meta.ContactInformation;
// Reference = meta.Meta.Reference;
// }
// else
// {
// Title = go.name;
// Version = "0.0";
// }
}
// //
// // Meta
// //
// // var meta = ExportRoot == null ? null : go.GetComponent<VRMMeta>();
// // if (meta != null && meta.Meta != null)
// // {
// // Title = meta.Meta.Title;
// // Version = string.IsNullOrEmpty(meta.Meta.Version) ? "0.0" : meta.Meta.Version;
// // Author = meta.Meta.Author;
// // ContactInformation = meta.Meta.ContactInformation;
// // Reference = meta.Meta.Reference;
// // }
// // else
// // {
// // Title = go.name;
// // Version = "0.0";
// // }
// }
}
}

View File

@@ -8,23 +8,23 @@ namespace VRM
{
const string CONVERT_HUMANOID_KEY = VRMVersion.MENU + "/Export humanoid";
[MenuItem(CONVERT_HUMANOID_KEY, true, 1)]
private static bool ExportValidate()
{
var root = Selection.activeObject as GameObject;
if (root == null)
{
return false;
}
// [MenuItem(CONVERT_HUMANOID_KEY, true, 1)]
// private static bool ExportValidate()
// {
// var root = Selection.activeObject as GameObject;
// if (root == null)
// {
// return false;
// }
var animator = root.GetComponent<Animator>();
if (animator == null)
{
return false;
}
// var animator = root.GetComponent<Animator>();
// if (animator == null)
// {
// return false;
// }
return true;
}
// return true;
// }
[MenuItem(CONVERT_HUMANOID_KEY, false, 1)]
private static void ExportFromMenu()

View File

@@ -15,7 +15,12 @@ namespace VRM
public class VRMExporterWizard : EditorWindow
{
[SerializeField]
public VRMExportSettings m_settings = new VRMExportSettings();
public GameObject ExportRoot;
SerializedProperty m_exportRoot;
[SerializeField]
public VRMExportSettings m_settings;
VRMMetaObject m_meta;
VRMMetaObject Meta
@@ -24,16 +29,37 @@ namespace VRM
set
{
if (m_meta == value) return;
if (m_meta != null)
if (m_metaEditor != null)
{
UnityEditor.Editor.DestroyImmediate(m_metaEditor);
m_metaEditor = null;
}
m_meta = value;
if (m_meta == null)
}
}
void UpdateRoot(GameObject root)
{
if (root == ExportRoot)
{
return;
}
ExportRoot = root;
if (ExportRoot == null)
{
Meta = null;
}
else
{
var meta = ExportRoot.GetComponent<VRMMeta>();
if (meta != null)
{
m_meta = TmpMeta;
Meta = meta.Meta;
}
else
{
Meta = null;
}
// m_metaEditor = Editor.CreateEditor(m_meta);
}
}
@@ -66,6 +92,7 @@ namespace VRM
UnityEditor.Editor.DestroyImmediate(m_Inspector);
Meta = null;
ScriptableObject.DestroyImmediate(m_tmpMeta);
ScriptableObject.DestroyImmediate(m_settings);
}
private void InvokeWizardUpdate()
@@ -104,6 +131,10 @@ namespace VRM
{
EditorGUIUtility.labelWidth = 150;
EditorGUILayout.LabelField("ExportRoot");
var root = (GameObject)EditorGUILayout.ObjectField(ExportRoot, typeof(GameObject), true);
UpdateRoot(root);
// Render contents using Generic Inspector GUI
m_ScrollPosition = BeginVerticalScrollView(m_ScrollPosition, false, GUI.skin.verticalScrollbar, "OL Box");
GUIUtility.GetControlID(645789, FocusType.Passive);
@@ -162,19 +193,32 @@ namespace VRM
protected virtual bool DrawWizardGUI()
{
if (Meta != null)
{
if (m_metaEditor == null)
{
m_metaEditor = Editor.CreateEditor(Meta);
if (Meta != null)
{
m_metaEditor = Editor.CreateEditor(Meta);
}
else
{
m_metaEditor = Editor.CreateEditor(TmpMeta);
}
}
EditorGUILayout.LabelField("Meta ", EditorStyles.boldLabel);
m_metaEditor.OnInspectorGUI();
}
{
if (m_Inspector == null)
{
m_Inspector = Editor.CreateEditor(this);
if (m_settings == null)
{
m_settings = ScriptableObject.CreateInstance<VRMExportSettings>();
}
m_Inspector = Editor.CreateEditor(m_settings);
}
EditorGUILayout.Space();
EditorGUILayout.LabelField("Export Settings ", EditorStyles.boldLabel);
m_Inspector.OnInspectorGUI();
}
return true;
@@ -284,7 +328,7 @@ namespace VRM
var go = Selection.activeObject as GameObject;
// update checkbox
wiz.m_settings.InitializeFrom(go);
wiz.UpdateRoot(go);
wiz.OnWizardUpdate();
}
@@ -315,7 +359,7 @@ namespace VRM
var path = EditorUtility.SaveFilePanel(
"Save vrm",
directory,
m_settings.Source.name + EXTENSION,
ExportRoot.name + EXTENSION,
EXTENSION.Substring(1));
if (string.IsNullOrEmpty(path))
{
@@ -324,41 +368,26 @@ namespace VRM
m_lastExportDir = Path.GetDirectoryName(path).Replace("\\", "/");
// export
VRMEditorExporter.Export(path, m_settings);
VRMEditorExporter.Export(path, ExportRoot, m_settings);
}
void OnWizardUpdate()
{
m_validations.Clear();
m_validations.AddRange(m_settings.Validate());
if (Meta != null)
{
m_validations.AddRange(Meta.Validate());
}
else
{
m_validations.Add(Validation.Error("meta がありません"));
}
// m_validations.Clear();
// m_validations.AddRange(m_settings.Validate());
// if (Meta != null)
// {
// m_validations.AddRange(Meta.Validate());
// }
// else
// {
// m_validations.Add(Validation.Error("meta がありません"));
// }
var hasError = m_validations.Any(x => !x.CanExport);
m_IsValid = !hasError;
// var hasError = m_validations.Any(x => !x.CanExport);
// m_IsValid = !hasError;
if (m_settings.Source == null)
{
Meta = null;
}
else
{
var meta = m_settings.Source.GetComponent<VRMMeta>();
if (meta != null)
{
Meta = meta.Meta;
}
else
{
Meta = null;
}
}
UpdateRoot(ExportRoot);
Repaint();
// GUIUtility.ExitGUI();

View File

@@ -87,10 +87,7 @@ namespace VRM
private void OnEnable()
{
// m_ScriptProp = serializedObject.FindProperty("m_Script");
if (serializedObject != null)
{
InitMap(serializedObject);
}
InitMap(serializedObject);
}
public override void OnInspectorGUI()
@@ -115,6 +112,7 @@ namespace VRM
so.Update();
GUI.enabled = false;
EditorGUILayout.PropertyField(m_propMap["ExporterVersion"]);
if (VRMVersion.IsNewer(m_propMap["ExporterVersion"].stringValue))
{
@@ -125,14 +123,15 @@ namespace VRM
m_foldoutInfo = EditorGUILayout.Foldout(m_foldoutInfo, "Information");
if (m_foldoutInfo)
{
// texture
var thumbnail = m_propMap["Thumbnail"];
EditorGUILayout.PropertyField(thumbnail);
thumbnail.objectReferenceValue = TextureField("", (Texture2D)thumbnail.objectReferenceValue, 100);
foreach (var kv in m_customPropMap)
{
kv.Value.OnGUI();
}
var thumbnail = m_propMap["Thumbnail"];
EditorGUILayout.PropertyField(thumbnail);
thumbnail.objectReferenceValue = TextureField("", (Texture2D)thumbnail.objectReferenceValue, 100);
}
EditorGUILayout.LabelField("License ", EditorStyles.boldLabel);

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 703726d4973c85447a3bd2ae30c760f0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: