diff --git a/Scripts/Format/Editor/VRMExportObjectEditor.cs b/Scripts/Format/Editor/VRMExportObjectEditor.cs new file mode 100644 index 000000000..9a6fffd51 --- /dev/null +++ b/Scripts/Format/Editor/VRMExportObjectEditor.cs @@ -0,0 +1,111 @@ +using System; +using UnityEditor; +using UnityEngine; + + +namespace VRM +{ + [CustomEditor(typeof(VRMExportObject))] + public class VRMExportObjectEditor : Editor + { + SerializedProperty m_settings; + VRMExportObject m_target; + + void OnEnable() + { + m_target = target as VRMExportObject; + m_settings = serializedObject.FindProperty("Settings"); + } + + public override void OnInspectorGUI() + { + // + // Editor + // + serializedObject.Update(); + + var before = m_target.Settings.Source; + + EditorGUILayout.PropertyField(m_settings, true); + serializedObject.ApplyModifiedProperties(); + + // + // + // + var after = m_target.Settings.Source; + if (before != after) + { + m_target.Settings.InitializeFrom(after as GameObject); + } + + bool canExport = m_target.Settings.Source != null; + foreach (var msg in m_target.Settings.CanExport()) + { + canExport = false; + EditorGUILayout.HelpBox(msg, MessageType.Error); + } + + if (canExport) + { + if (GUILayout.Button("Export")) + { + var path = EditorUtility.SaveFilePanel( + "Save vrm", + null,//Dir, + m_target.Settings.Source.name + ".vrm", + "vrm"); + if (!string.IsNullOrEmpty(path)) + { + Export(path); + } + } + } + } + + class DisposableInstance : IDisposable + { + GameObject m_go; + public GameObject GameObject + { + get + { + return m_go; + } + } + + public DisposableInstance(GameObject prefab) + { + m_go = GameObject.Instantiate(prefab); + } + + public void Dispose() + { + if (m_go != null) + { + if (Application.isPlaying) + { + GameObject.Destroy(m_go); + } + else + { + GameObject.DestroyImmediate(m_go); + } + } + } + } + + void Export(string path) + { + Debug.LogFormat("export: {0}", path); + + /* + using (var instance = new DisposableInstance(m_source.objectReferenceValue as GameObject)) + { + var vrm = VRMExporter.Export(instance.GameObject); + var bytes = vrm.ToGlbBytes(); + File.WriteAllBytes(path, bytes); + } + */ + } + } +} diff --git a/Scripts/Format/Editor/VRMExportObjectEditor.cs.meta b/Scripts/Format/Editor/VRMExportObjectEditor.cs.meta new file mode 100644 index 000000000..9a7ef2be7 --- /dev/null +++ b/Scripts/Format/Editor/VRMExportObjectEditor.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 01708ecf1aa756948be6996d987684a7 +timeCreated: 1532063961 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/Format/Editor/VRMExporterMenu.cs b/Scripts/Format/Editor/VRMExporterMenu.cs index 8782ebcb6..c60a7be1b 100644 --- a/Scripts/Format/Editor/VRMExporterMenu.cs +++ b/Scripts/Format/Editor/VRMExporterMenu.cs @@ -13,104 +13,58 @@ namespace VRM { const string EXTENSION = ".vrm"; - public Animator Target; VRMMeta m_meta; - public string Title; - - public string Author; - - public bool ForceTPose; - - public bool PoseFreeze; + public VRMExportSettings m_settings = new VRMExportSettings(); public static void CreateWizard() { var wiz = ScriptableWizard.DisplayWizard( "VRM Exporter", "Export"); var go = Selection.activeObject as GameObject; - if (go != null) - { - wiz.Target = go.GetComponent(); - } // update checkbox - var desc = wiz.Target.GetComponent(); - if (desc == null) - { - wiz.ForceTPose = true; - wiz.PoseFreeze = true; - } - - var meta = wiz.Target.GetComponent(); - if (meta != null && meta.Meta != null) - { - wiz.Title = meta.Meta.Title; - wiz.Author = meta.Meta.Author; - } - else - { - wiz.Title = wiz.Target.name; - } + wiz.m_settings.InitializeFrom(go); wiz.OnWizardUpdate(); } - string m_dir; - string Dir - { - get - { - if (m_dir == null) - { - m_dir = Path.GetFullPath(Application.dataPath); ; - } - return m_dir; - } - set - { - m_dir = value; - } - } - void OnWizardCreate() { // save dialog - Debug.LogFormat("OnWizardCreate: {0}", Dir); var path = EditorUtility.SaveFilePanel( "Save vrm", - Dir, - Target.name + EXTENSION, + null, + m_settings.Source.name + EXTENSION, EXTENSION.Substring(1)); if (string.IsNullOrEmpty(path)) { return; } - Dir = Path.GetDirectoryName(path); // export - var target = Target.gameObject; - if (PoseFreeze) + var target = m_settings.Source; + if (m_settings.PoseFreeze) { - Undo.RecordObjects(Target.transform.Traverse().ToArray(), "before normalize"); + Undo.RecordObjects(m_settings.Source.transform.Traverse().ToArray(), "before normalize"); var map = new Dictionary(); - target = VRM.BoneNormalizer.Execute(Target.gameObject, map, ForceTPose); - VRMHumanoidNorimalizerMenu.CopyVRMComponents(Target.gameObject, target, map); + target = VRM.BoneNormalizer.Execute(m_settings.Source.gameObject, map, m_settings.ForceTPose); + VRMHumanoidNorimalizerMenu.CopyVRMComponents(m_settings.Source.gameObject, target, map); Undo.PerformUndo(); } var sw = System.Diagnostics.Stopwatch.StartNew(); var vrm = VRMExporter.Export(target); - vrm.extensions.VRM.meta.title = Title; - vrm.extensions.VRM.meta.author = Author; + vrm.extensions.VRM.meta.title = m_settings.Title; + vrm.extensions.VRM.meta.author = m_settings.Author; var bytes = vrm.ToGlbBytes(); File.WriteAllBytes(path, bytes); Debug.LogFormat("Export elapsed {0}", sw.Elapsed); - if (Target.gameObject != target) + if (m_settings.Source.gameObject != target) { GameObject.DestroyImmediate(target); } @@ -127,38 +81,10 @@ namespace VRM var helpBuilder = new StringBuilder(); var errorBuilder = new StringBuilder(); - if (Target == null) + foreach(var msg in m_settings.CanExport()) { isValid = false; - errorBuilder.Append("Require animator. "); - } - else if (Target.avatar == null) - { - isValid = false; - errorBuilder.Append("Require animator.avatar. "); - } - else if (!Target.avatar.isValid) - { - isValid = false; - errorBuilder.Append("Animator.avatar is not valid. "); - } - else if (!Target.avatar.isHuman) - { - isValid = false; - errorBuilder.Append("Animator.avatar is not humanoid. Please change model's AnimationType to humanoid. "); - } - - - if (string.IsNullOrEmpty(Title)) - { - isValid = false; - errorBuilder.Append("Require Title. "); - } - - if (string.IsNullOrEmpty(Author)) - { - isValid = false; - errorBuilder.Append("Require Author. "); + errorBuilder.Append(msg); } helpString = helpBuilder.ToString(); diff --git a/Scripts/Format/VRMExporSettings.cs b/Scripts/Format/VRMExporSettings.cs new file mode 100644 index 000000000..747481cdd --- /dev/null +++ b/Scripts/Format/VRMExporSettings.cs @@ -0,0 +1,88 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + + +namespace VRM +{ + [Serializable] + public class VRMExportSettings + { + public GameObject Source; + + public string Title; + + public string Author; + + public bool ForceTPose = true; + + public bool PoseFreeze = true; + + public IEnumerable CanExport() + { + if (Source == null) + { + yield return "Require source"; + yield break; + } + + var animator = Source.GetComponent(); + if (animator == null) + { + yield return "Require animator. "; + } + else if (animator.avatar == null) + { + yield return "Require animator.avatar. "; + } + else if (!animator.avatar.isValid) + { + yield return "Animator.avatar is not valid. "; + } + else if (!animator.avatar.isHuman) + { + yield return "Animator.avatar is not humanoid. Please change model's AnimationType to humanoid. "; + } + + if (string.IsNullOrEmpty(Title)) + { + yield return "Require Title. "; + } + + if (string.IsNullOrEmpty(Author)) + { + yield return "Require Author. "; + } + } + + public void InitializeFrom(GameObject go) + { + if (Source == go) return; + Source = go; + + var desc = Source == null ? null : go.GetComponent(); + if (desc == null) + { + ForceTPose = true; + PoseFreeze = true; + } + else + { + ForceTPose = false; + PoseFreeze = false; + } + + var meta = Source == null ? null : go.GetComponent(); + if (meta != null && meta.Meta != null) + { + Title = meta.Meta.Title; + Author = meta.Meta.Author; + } + else + { + Title = go.name; + //Author = ""; + } + } + } +} diff --git a/Scripts/Format/VRMExporSettings.cs.meta b/Scripts/Format/VRMExporSettings.cs.meta new file mode 100644 index 000000000..d80644aa3 --- /dev/null +++ b/Scripts/Format/VRMExporSettings.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: f1bcfcc2d4692ef41b0c8f0f9ec3df14 +timeCreated: 1532066746 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/Format/VRMExportObject.cs b/Scripts/Format/VRMExportObject.cs new file mode 100644 index 000000000..c278f1a52 --- /dev/null +++ b/Scripts/Format/VRMExportObject.cs @@ -0,0 +1,12 @@ +using UnityEngine; + + +namespace VRM +{ + [CreateAssetMenu(menuName = "VRM/ExportObject")] + public class VRMExportObject : ScriptableObject + { + [SerializeField] + public VRMExportSettings Settings; + } +} diff --git a/Scripts/Format/VRMExportObject.cs.meta b/Scripts/Format/VRMExportObject.cs.meta new file mode 100644 index 000000000..90b6df455 --- /dev/null +++ b/Scripts/Format/VRMExportObject.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: f8ed5cb82dd13bf43a1556b24a6d13a0 +timeCreated: 1532063757 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: