disable process button if not validated

This commit is contained in:
ousttrue 2022-05-17 13:25:17 +09:00
parent 5fd2a743a1
commit 41a7aeda65
5 changed files with 112 additions and 94 deletions

View File

@ -8,7 +8,7 @@ namespace UniGLTF.MeshUtility
public class MeshProcessDialog : EditorWindow
{
const string TITLE = "Mesh Processing Window";
public MeshProcessDialogTabs Tab;
MeshProcessDialogTabs _tab;
private GameObject _exportTarget;
@ -42,40 +42,28 @@ namespace UniGLTF.MeshUtility
}
}
static bool IsGameObjectSelected()
{
return Selection.activeObject != null && Selection.activeObject is GameObject;
}
private void OnGUI()
{
_scrollPos = EditorGUILayout.BeginScrollView(_scrollPos);
EditorGUIUtility.labelWidth = 300;
// lang
EditorGUIUtility.labelWidth = 200;
LanguageGetter.OnGuiSelectLang();
_exportTarget = (GameObject)EditorGUILayout.ObjectField(MeshProcessingMessages.TARGET_OBJECT.Msg(), _exportTarget, typeof(GameObject), true);
_tab = TabBar.OnGUI(_tab, "LargeButton", GUI.ToolbarButtonSize.Fixed);
{
// _exportTarget
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField(MeshProcessingMessages.TARGET_OBJECT.Msg(), GUILayout.MaxWidth(146.0f));
_exportTarget = (GameObject)EditorGUILayout.ObjectField(_exportTarget, typeof(GameObject), true);
EditorGUILayout.EndHorizontal();
// auto select ?
if (_exportTarget == null && IsGameObjectSelected())
{
_exportTarget = Selection.activeObject as GameObject;
}
}
// tab
Tab = TabBar.OnGUI(Tab, "LargeButton", GUI.ToolbarButtonSize.Fixed);
var processed = false;
switch (Tab)
switch (_tab)
{
case MeshProcessDialogTabs.MeshSeparator:
{
EditorGUILayout.HelpBox(MeshProcessingMessages.MESH_SEPARATOR.Msg(), MessageType.Info);
processed = TabMeshSeparator.OnGUI(_exportTarget);
if (TabMeshSeparator.TryExecutable(_exportTarget, out string msg))
{
processed = TabMeshSeparator.OnGUI(_exportTarget);
}
else
{
EditorGUILayout.HelpBox(msg, MessageType.Error);
}
break;
}
@ -83,7 +71,14 @@ namespace UniGLTF.MeshUtility
{
EditorGUILayout.HelpBox(MeshProcessingMessages.MESH_INTEGRATOR.Msg(), MessageType.Info);
_separateByBlendShape = EditorGUILayout.Toggle(MeshProcessingMessages.MESH_SEPARATOR_BY_BLENDSHAPE.Msg(), _separateByBlendShape);
processed = TabMeshIntegrator.OnGUI(_exportTarget, _separateByBlendShape);
if (TabMeshIntegrator.TryExecutable(_exportTarget, out string msg))
{
processed = TabMeshIntegrator.OnGUI(_exportTarget, _separateByBlendShape);
}
else
{
EditorGUILayout.HelpBox(msg, MessageType.Error);
}
break;
}
@ -95,7 +90,14 @@ namespace UniGLTF.MeshUtility
_boneMeshEraserEditor.OnInspectorGUI();
}
_boneMeshRemoverValidator.Validate(_skinnedMeshRenderer, _eraseBones);
processed = TabBoneMeshRemover.OnGUI(_exportTarget, _skinnedMeshRenderer, _eraseBones);
if (TabBoneMeshRemover.TryExecutable(_exportTarget, _skinnedMeshRenderer, out string msg))
{
processed = TabBoneMeshRemover.OnGUI(_exportTarget, _skinnedMeshRenderer, _eraseBones);
}
else
{
EditorGUILayout.HelpBox(msg, MessageType.Error);
}
break;
}
}

View File

@ -80,8 +80,8 @@ namespace UniGLTF.MeshUtility
[LangMsg(Languages.en, "Skinned/Static mesh is not contained")]
NO_MESH,
[LangMsg(Languages.ja, "ターゲットオブジェクトはVRMモデルです。`VRM0-> MeshIntegrator`を使ってください")]
[LangMsg(Languages.en, "Target object is VRM model, use `VRM0 -> MeshIntegrator` instead")]
[LangMsg(Languages.ja, "BlendShapeClipが不整合を起こすので、`VRM0-> MeshIntegrator`を使ってください")]
[LangMsg(Languages.en, "Because BlendShapeClip causes inconsistency , use `VRM0 -> MeshIntegrator` instead")]
VRM_DETECTED,
}
}

View File

@ -13,6 +13,24 @@ namespace UniGLTF.MeshUtility
const string BONE_MESH_ERASER_NAME = "BoneMeshEraser";
const string ASSET_SUFFIX = ".mesh.asset";
public static bool TryExecutable(GameObject root, SkinnedMeshRenderer smr, out string msg)
{
if (root == null)
{
msg = MeshProcessingMessages.NO_GAMEOBJECT_SELECTED.Msg();
return false;
}
if (smr == null)
{
msg = MeshProcessingMessages.SELECT_SKINNED_MESH.Msg();
return false;
}
msg = "";
return true;
}
public static bool OnGUI(GameObject root, SkinnedMeshRenderer smr, List<BoneMeshEraser.EraseBone> eraseBones)
{
var _isInvokeSuccess = false;
@ -32,18 +50,6 @@ namespace UniGLTF.MeshUtility
private static bool Execute(GameObject root, SkinnedMeshRenderer smr, List<BoneMeshEraser.EraseBone> eraseBones)
{
if (root == null)
{
EditorUtility.DisplayDialog("Failed", MeshProcessingMessages.NO_GAMEOBJECT_SELECTED.Msg(), "ok");
return false;
}
if (smr == null)
{
EditorUtility.DisplayDialog("Failed", MeshProcessingMessages.SELECT_SKINNED_MESH.Msg(), "ok");
return false;
}
var bones = smr.bones;
var meshNode = new GameObject(BONE_MESH_ERASER_NAME);

View File

@ -7,21 +7,29 @@ namespace UniGLTF.MeshUtility
{
public static class TabMeshIntegrator
{
public static bool OnGUI(GameObject root, bool onlyBlendShapeRenderers)
public static bool TryExecutable(GameObject root, out string msg)
{
var _isInvokeSuccess = false;
GUILayout.BeginVertical();
// check
if (root == null)
{
GUILayout.BeginHorizontal();
GUILayout.FlexibleSpace();
if (GUILayout.Button("Process", GUILayout.MinWidth(100)))
{
_isInvokeSuccess = TabMeshIntegrator.Execute(root, onlyBlendShapeRenderers);
}
GUILayout.EndHorizontal();
msg = MeshProcessingMessages.NO_GAMEOBJECT_SELECTED.Msg();
return false;
}
GUILayout.EndVertical();
return _isInvokeSuccess;
if (HasVrm(root))
{
msg = MeshProcessingMessages.VRM_DETECTED.Msg();
return false;
}
if (root.GetComponentsInChildren<SkinnedMeshRenderer>().Length == 0 && root.GetComponentsInChildren<MeshFilter>().Length == 0)
{
msg = MeshProcessingMessages.NO_MESH.Msg();
return false;
}
msg = "";
return true;
}
const string VRM_META = "VRMMeta";
@ -40,28 +48,25 @@ namespace UniGLTF.MeshUtility
return false;
}
public static bool OnGUI(GameObject root, bool onlyBlendShapeRenderers)
{
var _isInvokeSuccess = false;
GUILayout.BeginVertical();
{
GUILayout.BeginHorizontal();
GUILayout.FlexibleSpace();
if (GUILayout.Button("Process", GUILayout.MinWidth(100)))
{
_isInvokeSuccess = TabMeshIntegrator.Execute(root, onlyBlendShapeRenderers);
}
GUILayout.EndHorizontal();
}
GUILayout.EndVertical();
return _isInvokeSuccess;
}
static bool Execute(GameObject root, bool onlyBlendShapeRenderers)
{
// check
if (root == null)
{
EditorUtility.DisplayDialog("Failed", MeshProcessingMessages.NO_GAMEOBJECT_SELECTED.Msg(), "ok");
return false;
}
if (HasVrm(root))
{
EditorUtility.DisplayDialog("Failed", MeshProcessingMessages.VRM_DETECTED.Msg(), "ok");
return false;
}
if (root.GetComponentsInChildren<SkinnedMeshRenderer>().Length == 0 && root.GetComponentsInChildren<MeshFilter>().Length == 0)
{
EditorUtility.DisplayDialog("Failed", MeshProcessingMessages.NO_MESH.Msg(), "ok");
return false;
}
// execute
var results = new List<MeshIntegrationResult>();
if (onlyBlendShapeRenderers)
{
@ -75,7 +80,6 @@ namespace UniGLTF.MeshUtility
// 統合結果を適用した新しいヒエラルキーをコピーから作成する
MeshIntegratorUtility.CopyAndReplaceWithResults(root, results);
return true;
}
}

View File

@ -12,15 +12,32 @@ namespace UniGLTF.MeshUtility
/// </summary>
public static class TabMeshSeparator
{
private static readonly Vector3 ZERO_MOVEMENT = Vector3.zero;
const string ASSET_SUFFIX = ".mesh.asset";
private const string ASSET_SUFFIX = ".mesh.asset";
enum BlendShapeLogic
private enum BlendShapeLogic
{
WithBlendShape,
WithoutBlendShape,
}
public static bool TryExecutable(GameObject root, out string msg)
{
if (root == null)
{
msg = MeshProcessingMessages.NO_GAMEOBJECT_SELECTED.Msg();
return false;
}
if (root.GetComponentsInChildren<SkinnedMeshRenderer>().Length == 0)
{
msg = MeshProcessingMessages.NO_SKINNED_MESH.Msg();
return false;
}
msg = "";
return true;
}
public static bool OnGUI(GameObject root)
{
var _isInvokeSuccess = false;
@ -38,36 +55,25 @@ namespace UniGLTF.MeshUtility
return _isInvokeSuccess;
}
static bool Execute(GameObject root)
private static bool Execute(GameObject root)
{
if (root == null)
{
EditorUtility.DisplayDialog("Failed", MeshProcessingMessages.NO_GAMEOBJECT_SELECTED.Msg(), "ok");
return false;
}
if (root.GetComponentsInChildren<SkinnedMeshRenderer>().Length == 0)
{
EditorUtility.DisplayDialog("Failed", MeshProcessingMessages.NO_SKINNED_MESH.Msg(), "ok");
return false;
}
// copy
var outputObject = GameObject.Instantiate(root);
outputObject.name = outputObject.name + "_mesh_separation";
// 改変と asset の作成
var list = SeparationProcessing(outputObject);
// asset の永続化
foreach (var (src, with, without) in list)
{
// asset の永続化
SaveMesh(src, with, BlendShapeLogic.WithBlendShape);
SaveMesh(src, without, BlendShapeLogic.WithoutBlendShape);
}
return true;
}
static void SaveMesh(Mesh mesh, Mesh newMesh, BlendShapeLogic blendShapeLabel)
private static void SaveMesh(Mesh mesh, Mesh newMesh, BlendShapeLogic blendShapeLabel)
{
// save mesh as asset
var assetPath = string.Format("{0}{1}", Path.GetFileNameWithoutExtension(mesh.name), ASSET_SUFFIX);
@ -98,7 +104,7 @@ namespace UniGLTF.MeshUtility
/// </summary>
/// <param name="go"></param>
/// <return>(Mesh 分割前, Mesh BlendShape有り、Mesh BlendShape無し)のリストを返す</return>
public static List<(Mesh Src, Mesh With, Mesh Without)> SeparationProcessing(GameObject go)
private static List<(Mesh Src, Mesh With, Mesh Without)> SeparationProcessing(GameObject go)
{
var list = new List<(Mesh Src, Mesh With, Mesh Without)>();
var skinnedMeshRenderers = go.GetComponentsInChildren<SkinnedMeshRenderer>();
@ -131,7 +137,7 @@ namespace UniGLTF.MeshUtility
for (int j = 0; j < deltaVertices.Length; j++)
{
if (!deltaVertices[j].Equals(ZERO_MOVEMENT))
if (!deltaVertices[j].Equals(Vector3.zero))
{
if (!indicesUsedByBlendShape.Values.Contains(j))
{