UniGLTF.MeshUtility.MeshIntegrationTab

This commit is contained in:
ousttrue 2023-11-17 19:58:10 +09:00
parent 8e6c005600
commit c0d29dd2e6
9 changed files with 205 additions and 250 deletions

View File

@ -1,43 +0,0 @@
using UniGLTF.M17N;
using UnityEditor;
using UnityEngine;
namespace UniGLTF.MeshUtility
{
/// <summary>
/// BoneMeshRemover 向けのエディタ。
///
/// SerializedProperty 経由で ユーザー定義 struct のフィールド
/// public List<BoneMeshEraser.EraseBone> _eraseBones;
/// を EditorGUILayout.PropertyField するための細工である。
///
/// SerializedObject は UnityEngine.Object から作成するので、
/// UnityEngine.Object を継承したクラスのフィールドに ユーザー定義 struct を配置する。
/// 持ち主の SerializedObject を経由して EditorGUILayout.PropertyField してる。
/// </summary>
[CustomEditor(typeof(MeshUtilityDialog), true)]
class BoneMeshEraserEditor : Editor
{
MeshUtilityDialog _targetDialog;
SerializedProperty _skinnedMesh;
SerializedProperty _eraseBones;
void OnEnable()
{
_targetDialog = target as MeshUtilityDialog;
if (_targetDialog)
{
_skinnedMesh = serializedObject.FindProperty(nameof(MeshUtilityDialog._skinnedMeshRenderer));
_eraseBones = serializedObject.FindProperty(nameof(MeshUtilityDialog._eraseBones));
}
}
public override void OnInspectorGUI()
{
serializedObject.Update();
EditorGUILayout.PropertyField(_skinnedMesh);
EditorGUILayout.PropertyField(_eraseBones);
serializedObject.ApplyModifiedProperties();
}
}
}

View File

@ -1,22 +1,21 @@
using System.Collections.Generic;
using UniGLTF.MeshUtility;
using UnityEditor;
using UnityEditorInternal;
using UnityEngine;
namespace UniVRM10
namespace UniGLTF.MeshUtility
{
class MeshIntegrationTab
public class MeshIntegrationTab
{
bool _modified = false;
Vrm10MeshUtility _meshUti;
protected GltfMeshUtility _meshUti;
Splitter _splitter;
ReorderableList _groupList;
ReorderableList _rendererList;
public List<Renderer> _renderers = new List<Renderer>();
int _selected = -1;
int Selected
protected int _selected = -1;
protected int Selected
{
set
{
@ -34,7 +33,7 @@ namespace UniVRM10
}
}
public MeshIntegrationTab(EditorWindow editor, Vrm10MeshUtility meshUtility)
public MeshIntegrationTab(EditorWindow editor, GltfMeshUtility meshUtility)
{
_meshUti = meshUtility;
_splitter = new VerticalSplitter(editor, 200, 50);
@ -66,11 +65,10 @@ namespace UniVRM10
};
}
public void UpdateMeshIntegrationList(GameObject root)
public virtual void UpdateMeshIntegrationList(GameObject root)
{
_selected = -1;
_meshUti.MeshIntegrationGroups.Clear();
_meshUti.IntegrateFirstPerson(root);
Selected = 0;
}

View File

@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 07d031dea01a55c43b1ec68cd10bf461
guid: 27b74253f485b4b45a8d2847ec3c2b34
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@ -2,34 +2,13 @@ using UnityEngine;
using UnityEditor;
using UniGLTF.M17N;
using System.Collections.Generic;
using System.Linq;
namespace UniGLTF.MeshUtility
{
public class MeshUtilityDialog : EditorWindow
{
public const string MENU_NAME = "glTF MeshUtility";
enum MeshProcessDialogTabs
{
MeshSeparator,
MeshIntegrator,
BoneMeshEraser,
}
MeshProcessDialogTabs _tab;
private GameObject _exportTarget;
[SerializeField]
public bool _separateByBlendShape = true;
[SerializeField]
public SkinnedMeshRenderer _skinnedMeshRenderer = null;
[SerializeField]
public List<BoneMeshEraser.EraseBone> _eraseBones;
private BoneMeshEraserEditor _boneMeshEraserEditor;
private Vector2 _scrollPos = new Vector2(0, 0);
public static void OpenWindow()
{
var window =
@ -38,82 +17,182 @@ namespace UniGLTF.MeshUtility
window.Show();
}
private void OnEnable()
protected enum Tabs
{
if (!_boneMeshEraserEditor)
Freeze,
IntegrateSplit,
BoneMeshEraser,
}
protected Tabs _tab;
protected GameObject _exportTarget;
GltfMeshUtility _meshUtil;
protected virtual GltfMeshUtility MeshUtility
{
get
{
_boneMeshEraserEditor = (BoneMeshEraserEditor)Editor.CreateEditor(this);
if (_meshUtil == null)
{
_meshUtil = new GltfMeshUtility();
}
return _meshUtil;
}
}
MeshIntegrationTab _integrationTab;
protected virtual MeshIntegrationTab MeshIntegration
{
get
{
if (_integrationTab == null)
{
_integrationTab = new MeshIntegrationTab(this, MeshUtility);
}
return _integrationTab;
}
}
protected List<Validation> _validations = new List<Validation>();
protected virtual void Validate()
{
_validations.Clear();
if (_exportTarget == null)
{
_validations.Add(Validation.Error("set target GameObject"));
return;
}
}
bool IsValid => !_validations.Any(v => !v.CanExport);
Vector2 _scrollPos;
void OnEnable()
{
}
private void OnGUI()
{
var modified = false;
_scrollPos = EditorGUILayout.BeginScrollView(_scrollPos);
EditorGUIUtility.labelWidth = 200;
LanguageGetter.OnGuiSelectLang();
_exportTarget = (GameObject)EditorGUILayout.ObjectField(MeshUtilityMessages.TARGET_OBJECT.Msg(), _exportTarget, typeof(GameObject), true);
var exportTarget = (GameObject)EditorGUILayout.ObjectField(
MeshUtilityMessages.TARGET_OBJECT.Msg(),
_exportTarget, typeof(GameObject), true);
if (exportTarget != _exportTarget)
{
_exportTarget = exportTarget;
MeshIntegration.UpdateMeshIntegrationList(_exportTarget);
modified = true;
}
_tab = TabBar.OnGUI(_tab, "LargeButton", GUI.ToolbarButtonSize.Fixed);
var processed = false;
foreach (var validation in _validations)
{
validation.DrawGUI();
}
EditorGUILayout.HelpBox(MeshUtilityMessages.MESH_SEPARATOR.Msg(), MessageType.Info);
EditorGUILayout.HelpBox(MeshUtilityMessages.MESH_INTEGRATOR.Msg(), MessageType.Info);
switch (_tab)
{
case MeshProcessDialogTabs.MeshSeparator:
case Tabs.Freeze:
{
EditorGUILayout.HelpBox(MeshUtilityMessages.MESH_SEPARATOR.Msg(), MessageType.Info);
if (TabMeshSeparator.TryExecutable(_exportTarget, out string msg))
if (MeshFreezeGui())
{
processed = TabMeshSeparator.OnGUI(_exportTarget);
}
else
{
EditorGUILayout.HelpBox(msg, MessageType.Error);
modified = true;
}
break;
}
case MeshProcessDialogTabs.MeshIntegrator:
case Tabs.IntegrateSplit:
{
EditorGUILayout.HelpBox(MeshUtilityMessages.MESH_INTEGRATOR.Msg(), MessageType.Info);
_separateByBlendShape = EditorGUILayout.Toggle(MeshUtilityMessages.MESH_SEPARATOR_BY_BLENDSHAPE.Msg(), _separateByBlendShape);
if (TabMeshIntegrator.TryExecutable(_exportTarget, out string msg))
if (MeshIntegrateGui())
{
if (GUILayout.Button("Process", GUILayout.MinWidth(100)))
{
processed = TabMeshIntegrator.Execute(_exportTarget, _separateByBlendShape);
}
}
else
{
EditorGUILayout.HelpBox(msg, MessageType.Error);
modified = true;
}
break;
}
case MeshProcessDialogTabs.BoneMeshEraser:
case Tabs.BoneMeshEraser:
{
// TODO: FirstPerson 処理と統合する
EditorGUILayout.HelpBox(MeshUtilityMessages.BONE_MESH_ERASER.Msg(), MessageType.Info);
if (_boneMeshEraserEditor)
{
_boneMeshEraserEditor.OnInspectorGUI();
}
if (TabBoneMeshRemover.TryExecutable(_exportTarget, _skinnedMeshRenderer, out string msg))
{
processed = TabBoneMeshRemover.OnGUI(_exportTarget, _skinnedMeshRenderer, _eraseBones);
}
else
{
EditorGUILayout.HelpBox(msg, MessageType.Error);
}
// if (_boneMeshEraserEditor)
// {
// _boneMeshEraserEditor.OnInspectorGUI();
// }
// if (TabBoneMeshRemover.TryExecutable(_exportTarget, _skinnedMeshRenderer, out string msg))
// {
// processed = TabBoneMeshRemover.OnGUI(_exportTarget, _skinnedMeshRenderer, _eraseBones);
// }
// else
// {
// EditorGUILayout.HelpBox(msg, MessageType.Error);
// }
break;
}
}
EditorGUILayout.EndScrollView();
if (processed)
if (modified)
{
Close();
GUIUtility.ExitGUI();
Validate();
}
GUI.enabled = IsValid;
var pressed = GUILayout.Button("Process", GUILayout.MinWidth(100));
GUI.enabled = true;
if (pressed)
{
Undo.RegisterFullObjectHierarchyUndo(exportTarget, "MeshUtility");
foreach (var go in MeshUtility.Process(exportTarget))
{
Undo.RegisterCreatedObjectUndo(go, "MeshUtility");
}
_exportTarget = null;
// Show Result ?
// Close();
// GUIUtility.ExitGUI();
}
}
protected bool ToggleIsModified(string label, ref bool value)
{
var newValue = EditorGUILayout.Toggle(label, value);
if (newValue == value)
{
return false;
}
value = newValue;
return true;
}
bool MeshFreezeGui()
{
var forceUniqueName = ToggleIsModified("ForceUniqueName", ref MeshUtility.ForceUniqueName);
var blendShape = ToggleIsModified("BlendShape", ref MeshUtility.FreezeBlendShape);
var scale = ToggleIsModified("Scale", ref MeshUtility.FreezeScaling);
var rotation = ToggleIsModified("Rotation", ref MeshUtility.FreezeRotation);
return forceUniqueName || blendShape || scale || rotation;
}
protected virtual bool MeshIntegrateGui()
{
var split = ToggleIsModified("Separate by BlendShape", ref MeshUtility.SplitByBlendShape);
var p = position;
var last = GUILayoutUtility.GetLastRect();
var y = last.y + last.height;
var rect = new Rect
{
x = last.x,
y = y,
width = p.width,
height = p.height - y
// process button の高さ
- 30
};
var mod = MeshIntegration.OnGui(rect);
return split || mod;
}
}
}

View File

@ -2,7 +2,7 @@ using UnityEngine;
using UnityEditor;
using System;
namespace UniVRM10
namespace UniGLTF.MeshUtility
{
[Serializable]
public abstract class Splitter

View File

@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 385274edf555ed84a9f3706ca2a99023
guid: dbb5f5bceb86592499a56fc18011553e
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@ -0,0 +1,23 @@
using UnityEditor;
using UnityEngine;
namespace UniVRM10
{
class Vrm10MeshIntegrationTab : UniGLTF.MeshUtility.MeshIntegrationTab
{
Vrm10MeshUtility _vrmMeshUtil;
public Vrm10MeshIntegrationTab(EditorWindow editor, Vrm10MeshUtility meshUtility) : base(editor, meshUtility)
{
_vrmMeshUtil = meshUtility;
}
public override void UpdateMeshIntegrationList(GameObject root)
{
_selected = -1;
_meshUti.MeshIntegrationGroups.Clear();
_vrmMeshUtil.IntegrateFirstPerson(root);
Selected = 0;
}
}
}

View File

@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: 2021859c0d7255643bd93c95ab3fcf3d
guid: ec2a4df10a08bab4a980b7203d341bda
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@ -1,163 +1,61 @@
using UnityEngine;
using UnityEditor;
using UniGLTF.M17N;
using System.Collections.Generic;
using UniGLTF.MeshUtility;
using UniGLTF;
using System.Linq;
namespace UniVRM10
{
public class Vrm10MeshUtilityDialog : EditorWindow
public class Vrm10MeshUtilityDialog : UniGLTF.MeshUtility.MeshUtilityDialog
{
public const string MENU_NAME = "VRM 1.0 MeshUtility";
enum Tabs
{
Freeze,
IntegrateSplit,
}
Tabs _tab;
public static void OpenWindow()
public new const string MENU_NAME = "VRM 1.0 MeshUtility";
public new static void OpenWindow()
{
var window =
(Vrm10MeshUtilityDialog)EditorWindow.GetWindow(typeof(Vrm10MeshUtilityDialog));
window.titleContent = new GUIContent(MENU_NAME);
window.Show();
}
Vrm10MeshUtility _meshUtility = new Vrm10MeshUtility();
List<Validation> _validations = new List<Validation>();
private void Validate()
protected override void Validate()
{
_validations.Clear();
if (_exportTarget == null)
{
_validations.Add(Validation.Error("set vrm1"));
return;
}
base.Validate();
if (_exportTarget.GetComponent<Vrm10Instance>() == null)
{
_validations.Add(Validation.Error("target is not vrm1"));
return;
}
}
bool IsValid => !_validations.Any(v => !v.CanExport);
Vector2 _scrollPos;
GameObject _exportTarget;
MeshIntegrationTab _meshIntegration;
void OnEnable()
Vrm10MeshUtility _meshUtil;
Vrm10MeshUtility Vrm10MeshUtility
{
_meshIntegration = new MeshIntegrationTab(this, _meshUtility);
}
private void OnGUI()
{
var modified = false;
_scrollPos = EditorGUILayout.BeginScrollView(_scrollPos);
EditorGUIUtility.labelWidth = 200;
LanguageGetter.OnGuiSelectLang();
var exportTarget = (GameObject)EditorGUILayout.ObjectField(
MeshUtilityMessages.TARGET_OBJECT.Msg(),
_exportTarget, typeof(GameObject), true);
if (exportTarget != _exportTarget)
get
{
_exportTarget = exportTarget;
_meshIntegration.UpdateMeshIntegrationList(_exportTarget);
modified = true;
}
_tab = TabBar.OnGUI(_tab, "LargeButton", GUI.ToolbarButtonSize.Fixed);
foreach (var validation in _validations)
{
validation.DrawGUI();
}
switch (_tab)
{
case Tabs.Freeze:
{
if (MeshFreezeGui())
{
modified = true;
}
break;
}
case Tabs.IntegrateSplit:
{
if (MeshIntegrateGui())
{
modified = true;
}
break;
}
}
EditorGUILayout.EndScrollView();
if (modified)
{
Validate();
}
GUI.enabled = IsValid;
var pressed = GUILayout.Button("Process", GUILayout.MinWidth(100));
GUI.enabled = true;
if (pressed)
{
Undo.RegisterFullObjectHierarchyUndo(exportTarget, "MeshUtility");
foreach (var go in _meshUtility.Process(exportTarget))
if (_meshUtil == null)
{
Undo.RegisterCreatedObjectUndo(go, "MeshUtility");
_meshUtil = new Vrm10MeshUtility();
}
_exportTarget = null;
// Show Result ?
// Close();
// GUIUtility.ExitGUI();
return _meshUtil;
}
}
protected override UniGLTF.MeshUtility.GltfMeshUtility MeshUtility => Vrm10MeshUtility;
Vrm10MeshIntegrationTab _integrationTab;
protected override UniGLTF.MeshUtility.MeshIntegrationTab MeshIntegration
{
get
{
if (_integrationTab == null)
{
_integrationTab = new Vrm10MeshIntegrationTab(this, Vrm10MeshUtility);
}
return _integrationTab;
}
}
bool ToggleIsModified(string label, ref bool value)
protected override bool MeshIntegrateGui()
{
var newValue = EditorGUILayout.Toggle(label, value);
if (newValue == value)
{
return false;
}
value = newValue;
return true;
}
bool MeshFreezeGui()
{
var forceUniqueName = ToggleIsModified("ForceUniqueName", ref _meshUtility.ForceUniqueName);
var blendShape = ToggleIsModified("BlendShape", ref _meshUtility.FreezeBlendShape);
var scale = ToggleIsModified("Scale", ref _meshUtility.FreezeScaling);
var rotation = ToggleIsModified("Rotation", ref _meshUtility.FreezeRotation);
return forceUniqueName || blendShape || scale || rotation;
}
bool MeshIntegrateGui()
{
var firstPerson = ToggleIsModified("FirstPerson == AUTO の生成", ref _meshUtility.GenerateMeshForFirstPersonAuto);
var split = ToggleIsModified("Separate by BlendShape", ref _meshUtility.SplitByBlendShape);
var p = position;
var last = GUILayoutUtility.GetLastRect();
var y = last.y + last.height;
var rect = new Rect
{
x = last.x,
y = y,
width = p.width,
height = p.height - y
// process button の高さ
- 30
};
var mod = _meshIntegration.OnGui(rect);
return firstPerson || split || mod;
var firstPerson = ToggleIsModified("FirstPerson == AUTO の生成", ref MeshUtility.GenerateMeshForFirstPersonAuto);
var mod = base.MeshIntegrateGui();
return firstPerson || mod;
}
}
}