ExportDialogBase

This commit is contained in:
ousttrue
2021-04-19 19:29:05 +09:00
parent 25ea39cd87
commit 7d5d323ead
3 changed files with 234 additions and 161 deletions

View File

@@ -0,0 +1,174 @@
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEditor;
using UnityEngine;
namespace UniGLTF
{
/// <summary>
/// ヒエラルキーをエクスポートするダイアログ。
///
/// * Root管理(m_state)
/// * Validation管理(Exportボタンを押せるか否か)
///
/// </summary>
public abstract class ExportDialogBase : EditorWindow
{
ExporterDialogState m_state;
protected ExporterDialogState State => m_state;
protected virtual void OnEnable()
{
Undo.willFlushUndoRecord += Repaint;
Selection.selectionChanged += Repaint;
m_state = new ExporterDialogState();
m_state.ExportRootChanged += (root) =>
{
Repaint();
};
m_state.ExportRoot = Selection.activeObject as GameObject;
Initialize();
}
protected abstract void Initialize();
void OnDisable()
{
Clear();
m_state.Dispose();
Selection.selectionChanged -= Repaint;
Undo.willFlushUndoRecord -= Repaint;
}
protected abstract void Clear();
//
// scroll
//
public delegate Vector2 BeginVerticalScrollViewFunc(Vector2 scrollPosition, bool alwaysShowVertical, GUIStyle verticalScrollbar, GUIStyle background, params GUILayoutOption[] options);
static BeginVerticalScrollViewFunc s_func;
static BeginVerticalScrollViewFunc BeginVerticalScrollView
{
get
{
if (s_func == null)
{
var methods = typeof(EditorGUILayout).GetMethods(BindingFlags.Static | BindingFlags.NonPublic).Where(x => x.Name == "BeginVerticalScrollView").ToArray();
var method = methods.First(x => x.GetParameters()[1].ParameterType == typeof(bool));
s_func = (BeginVerticalScrollViewFunc)method.CreateDelegate(typeof(BeginVerticalScrollViewFunc));
}
return s_func;
}
}
private Vector2 m_ScrollPosition;
//
// validation
//
protected abstract IEnumerable<Validator> ValidatorFactory();
void OnGUI()
{
var modified = false;
if (BeginGUI())
{
modified = DoGUI();
}
EndGUI();
if (modified)
{
State.Invalidate();
}
}
protected abstract bool DoGUI();
bool BeginGUI()
{
// ArgumentException: Getting control 1's position in a group with only 1 controls when doing repaint Aborting
// Validation により GUI の表示項目が変わる場合があるので、
// EventType.Layout と EventType.Repaint 間で内容が変わらないようしている。
if (Event.current.type == EventType.Layout)
{
State.Validate(ValidatorFactory());
}
EditorGUIUtility.labelWidth = 150;
// lang
Getter.OnGuiSelectLang();
EditorGUILayout.LabelField("ExportRoot");
{
State.ExportRoot = (GameObject)EditorGUILayout.ObjectField(State.ExportRoot, typeof(GameObject), true);
}
// Render contents using Generic Inspector GUI
m_ScrollPosition = BeginVerticalScrollView(m_ScrollPosition, false, GUI.skin.verticalScrollbar, "OL Box");
GUIUtility.GetControlID(645789, FocusType.Passive);
// validation
foreach (var v in State.Validations)
{
v.DrawGUI();
if (v.ErrorLevel == ErrorLevels.Critical)
{
// Export UI を表示しない
return false;
}
}
return true;
}
protected abstract string SaveTitle { get; }
protected abstract string SaveName { get; }
protected abstract string[] SaveExtensions { get; }
void EndGUI()
{
EditorGUILayout.EndScrollView();
//
// export button
//
// Create and Other Buttons
{
// errors
GUILayout.BeginVertical();
// GUILayout.FlexibleSpace();
{
GUILayout.BeginHorizontal();
GUILayout.FlexibleSpace();
GUI.enabled = State.Validations.All(x => x.CanExport);
if (GUILayout.Button("Export", GUILayout.MinWidth(100)))
{
var path = SaveFileDialog.GetPath(SaveTitle, SaveName, SaveExtensions);
if (!string.IsNullOrEmpty(path))
{
ExportPath(path);
// close
Close();
GUIUtility.ExitGUI();
}
}
GUI.enabled = true;
GUILayout.EndHorizontal();
}
GUILayout.EndVertical();
}
GUILayout.Space(8);
}
protected abstract void ExportPath(string path);
}
}

View File

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

View File

@@ -1,7 +1,6 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using UniGLTF.Animation;
using UnityEditor;
using UnityEngine;
@@ -9,7 +8,7 @@ using VRMShaders;
namespace UniGLTF
{
public class GltfExportWindow : EditorWindow
public class GltfExportWindow : ExportDialogBase
{
const string MENU_KEY = UniGLTFVersion.MENU + "/Export " + UniGLTFVersion.UNIGLTF_VERSION;
@@ -22,6 +21,46 @@ namespace UniGLTF
}
private static void Export(GameObject go, string path, MeshExportSettings settings, Axises inverseAxis)
{
}
GltfExportSettings m_settings;
Editor m_settingsInspector;
protected override void Initialize()
{
m_settings = ScriptableObject.CreateInstance<GltfExportSettings>();
m_settingsInspector = Editor.CreateEditor(m_settings);
}
protected override void Clear()
{
// m_settingsInspector
UnityEditor.Editor.DestroyImmediate(m_settingsInspector);
m_settingsInspector = null;
}
protected override IEnumerable<Validator> ValidatorFactory()
{
yield return HierarchyValidator.ValidateRoot;
yield return AnimationValidator.Validate;
if (!State.ExportRoot)
{
yield break;
}
}
protected override bool DoGUI()
{
m_settings.Root = State.ExportRoot;
m_settingsInspector.OnInspectorGUI();
return true;
}
protected override string SaveTitle => "Save gltf";
protected override string SaveName => $"{State.ExportRoot.name}.glb";
protected override string[] SaveExtensions => new string[] { "glb", "gltf" };
protected override void ExportPath(string path)
{
var ext = Path.GetExtension(path).ToLower();
var isGlb = false;
@@ -33,9 +72,15 @@ namespace UniGLTF
}
var gltf = new glTF();
using (var exporter = new gltfExporter(gltf, inverseAxis))
using (var exporter = new gltfExporter(gltf, m_settings.InverseAxis))
{
exporter.Prepare(go);
exporter.Prepare(State.ExportRoot);
var settings = new MeshExportSettings
{
ExportOnlyBlendShapePosition = m_settings.DropNormal,
UseSparseAccessorForMorphTarget = m_settings.Sparse,
DivideVertexBuffer = m_settings.DivideVertexBuffer,
};
exporter.Export(settings, AssetTextureUtil.IsTextureEditorAsset, AssetTextureUtil.GetTextureBytesWithMime);
}
@@ -64,164 +109,7 @@ namespace UniGLTF
AssetDatabase.ImportAsset(path.ToUnityRelativePath());
AssetDatabase.Refresh();
}
}
ExporterDialogState m_state;
GltfExportSettings m_settings;
Editor m_settingsInspector;
void OnEnable()
{
// Debug.Log("OnEnable");
Undo.willFlushUndoRecord += Repaint;
Selection.selectionChanged += Repaint;
m_settings = ScriptableObject.CreateInstance<GltfExportSettings>();
m_settingsInspector = Editor.CreateEditor(m_settings);
m_state = new ExporterDialogState();
m_state.ExportRootChanged += (root) =>
{
Repaint();
};
m_state.ExportRoot = Selection.activeObject as GameObject;
}
void OnDisable()
{
m_state.Dispose();
// Debug.Log("OnDisable");
Selection.selectionChanged -= Repaint;
Undo.willFlushUndoRecord -= Repaint;
// m_settingsInspector
UnityEditor.Editor.DestroyImmediate(m_settingsInspector);
m_settingsInspector = null;
// m_settings
ScriptableObject.DestroyImmediate(m_settings);
m_settings = null;
}
public delegate Vector2 BeginVerticalScrollViewFunc(Vector2 scrollPosition, bool alwaysShowVertical, GUIStyle verticalScrollbar, GUIStyle background, params GUILayoutOption[] options);
static BeginVerticalScrollViewFunc s_func;
static BeginVerticalScrollViewFunc BeginVerticalScrollView
{
get
{
if (s_func == null)
{
var methods = typeof(EditorGUILayout).GetMethods(BindingFlags.Static | BindingFlags.NonPublic).Where(x => x.Name == "BeginVerticalScrollView").ToArray();
var method = methods.First(x => x.GetParameters()[1].ParameterType == typeof(bool));
s_func = (BeginVerticalScrollViewFunc)method.CreateDelegate(typeof(BeginVerticalScrollViewFunc));
}
return s_func;
}
}
private Vector2 m_ScrollPosition;
IEnumerable<Validator> ValidatorFactory()
{
yield return HierarchyValidator.ValidateRoot;
yield return AnimationValidator.Validate;
if (!m_state.ExportRoot)
{
yield break;
}
}
private void OnGUI()
{
// ArgumentException: Getting control 1's position in a group with only 1 controls when doing repaint Aborting
// Validation により GUI の表示項目が変わる場合があるので、
// EventType.Layout と EventType.Repaint 間で内容が変わらないようしている。
if (Event.current.type == EventType.Layout)
{
m_state.Validate(ValidatorFactory());
}
EditorGUIUtility.labelWidth = 150;
// lang
Getter.OnGuiSelectLang();
EditorGUILayout.LabelField("ExportRoot");
{
m_state.ExportRoot = (GameObject)EditorGUILayout.ObjectField(m_state.ExportRoot, typeof(GameObject), true);
}
// Render contents using Generic Inspector GUI
m_ScrollPosition = BeginVerticalScrollView(m_ScrollPosition, false, GUI.skin.verticalScrollbar, "OL Box");
GUIUtility.GetControlID(645789, FocusType.Passive);
bool modified = ScrollArea();
EditorGUILayout.EndScrollView();
// Create and Other Buttons
{
// errors
GUILayout.BeginVertical();
// GUILayout.FlexibleSpace();
{
GUILayout.BeginHorizontal();
GUILayout.FlexibleSpace();
GUI.enabled = m_state.Validations.All(x => x.CanExport);
if (GUILayout.Button("Export", GUILayout.MinWidth(100)))
{
var path = SaveFileDialog.GetPath("Save gltf", $"{m_state.ExportRoot.name}.glb", "glb", "gltf");
if (!string.IsNullOrEmpty(path))
{
// export
Export(m_state.ExportRoot, path, new MeshExportSettings
{
ExportOnlyBlendShapePosition = m_settings.DropNormal,
UseSparseAccessorForMorphTarget = m_settings.Sparse,
DivideVertexBuffer = m_settings.DivideVertexBuffer,
}, m_settings.InverseAxis);
// close
Close();
GUIUtility.ExitGUI();
}
}
GUI.enabled = true;
GUILayout.EndHorizontal();
}
GUILayout.EndVertical();
}
GUILayout.Space(8);
if (modified)
{
m_state.Invalidate();
}
}
bool ScrollArea()
{
//
// Validation
//
foreach (var v in m_state.Validations)
{
v.DrawGUI();
if (v.ErrorLevel == ErrorLevels.Critical)
{
// Export UI を表示しない
return false;
}
}
//
// GUI
//
m_settings.Root = m_state.ExportRoot;
m_settingsInspector.OnInspectorGUI();
return true;
}
}
}