Vrm10MeshUtilityDialog

This commit is contained in:
ousttrue
2023-10-24 19:37:46 +09:00
parent d4f0bb2899
commit 2c8983b1ae
9 changed files with 530 additions and 1 deletions

View File

@@ -5,7 +5,6 @@ using UnityEngine;
namespace UniGLTF.MeshUtility
{
public static class TabBar
{
/// <summary>

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 6fb2795d5ca5ce9449de94ea5fb94dde
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,158 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UniGLTF;
using UnityEditor;
using UnityEditorInternal;
using UnityEngine;
namespace UniVRM10
{
class MeshIntegrationAndSplit
{
class MeshIntegrationGroup
{
public string Name;
public List<Renderer> Renderers = new List<Renderer>();
}
List<MeshIntegrationGroup> _meshIntegrationList = new List<MeshIntegrationGroup>();
List<Renderer> _renderers = new List<Renderer>();
Splitter _splitter;
ReorderableList _groupList;
ReorderableList _rendererList;
int _selected = -1;
int Selected
{
set
{
if (_selected == value)
{
return;
}
if (value < 0 || value >= _meshIntegrationList.Count)
{
return;
}
_selected = value;
_renderers.Clear();
_renderers.AddRange(_meshIntegrationList[_selected].Renderers);
}
}
public MeshIntegrationAndSplit(EditorWindow editor)
{
_splitter = new VerticalSplitter(editor, 50, 50);
_groupList = new ReorderableList(_meshIntegrationList, typeof(MeshIntegrationGroup));
_groupList.drawHeaderCallback = (Rect rect) =>
{
GUI.Label(rect, "Integration group");
};
_groupList.drawElementCallback = (Rect rect, int index, bool isActive, bool isFocused) =>
{
var group = _meshIntegrationList[index];
EditorGUI.TextField(rect, group.Name);
};
_groupList.onSelectCallback = rl =>
{
Selected = (rl.selectedIndices.Count > 0) ? rl.selectedIndices[0] : -1;
};
_rendererList = new ReorderableList(_renderers, typeof(Renderer));
_rendererList.drawHeaderCallback = (Rect rect) =>
{
GUI.Label(rect, "Renderer");
};
_rendererList.drawElementCallback = (Rect rect, int index, bool isActive, bool isFocused) =>
{
var r = _renderers[index];
EditorGUI.ObjectField(rect, r, typeof(Renderer), true);
};
}
public void UpdateMeshIntegrationList(GameObject root)
{
_selected = -1;
_meshIntegrationList.Clear();
IntegrateFirstPerson(root);
Selected = 0;
}
void IntegrateAll(GameObject root)
{
if (root == null)
{
return;
}
_meshIntegrationList.Add(new MeshIntegrationGroup
{
Name = "ALL",
Renderers = root.GetComponentsInChildren<Renderer>().ToList(),
});
}
MeshIntegrationGroup GetOrCreateGroup(string name)
{
foreach (var g in _meshIntegrationList)
{
if (g.Name == name)
{
return g;
}
}
_meshIntegrationList.Add(new MeshIntegrationGroup
{
Name = name,
});
return _meshIntegrationList.Last();
}
void IntegrateFirstPerson(GameObject root)
{
if (root == null)
{
return;
}
var vrm1 = root.GetComponent<Vrm10Instance>();
if (vrm1 == null)
{
return;
}
var vrmObject = vrm1.Vrm;
if (vrmObject == null)
{
return;
}
var fp = vrmObject.FirstPerson;
if (fp == null)
{
return;
}
foreach (var a in fp.Renderers)
{
var g = GetOrCreateGroup(a.FirstPersonFlag.ToString());
g.Renderers.Add(a.GetRenderer(root.transform));
}
}
private void ShowGroup(Rect rect)
{
_groupList.DoList(rect);
}
private void ShowSelected(Rect rect)
{
_rendererList.DoList(rect);
}
public void OnGui(Rect rect)
{
_splitter.OnGUI(
rect,
ShowGroup,
ShowSelected);
}
}
}

View File

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

View File

@@ -0,0 +1,183 @@
using UnityEngine;
using UnityEditor;
using System;
namespace UniVRM10
{
[Serializable]
public abstract class Splitter
{
internal enum SplitMode
{
Horizontal,
Vertical,
}
protected float _value;
private EditorWindow _window;
private SplitMode _lockMode;
private float _lockValues;
private MouseCursor _mouseCursor;
protected float _barSize;
private bool _isResize;
private Rect _resizeRect;
private float _ratio = 0.5f;
private static readonly Color SPLITTER_COLOR = new Color(0, 0, 0, 1.0f);
private static readonly Color SPLITTER_COLOR_FREE = new Color(0.5f, 0.5f, 0.5f, 1.0f);
internal Splitter(EditorWindow window, float defaultValue, SplitMode lockMode, float minValue, float barSize = 16f)
{
_window = window;
_value = defaultValue;
_lockMode = lockMode;
_lockValues = minValue;
_mouseCursor = lockMode == SplitMode.Vertical ? MouseCursor.ResizeHorizontal : MouseCursor.ResizeVertical;
_barSize = barSize;
}
protected abstract RectOffset RectOffset();
protected abstract Rect MainRect(Rect rect);
protected abstract Rect SubRect(Rect rect);
protected abstract Rect BarRect(Rect rect);
public void OnGUI(Rect rect, Action<Rect> mainDelegate, Action<Rect> subDelegate)
{
var current = Event.current;
mainDelegate(MainRect(rect));
subDelegate(SubRect(rect));
_resizeRect = BarRect(rect);
EditorGUIUtility.AddCursorRect(_resizeRect, _mouseCursor);
var clampMax = _lockMode == SplitMode.Vertical ? rect.width - _lockValues : rect.height - _lockValues;
var targetSplitterValue = _lockMode == SplitMode.Vertical ? rect.width : rect.height;
_ratio = _lockMode == SplitMode.Vertical ? _value / rect.width : _value / rect.height;
if (current.type == EventType.MouseDown && _resizeRect.Contains(current.mousePosition))
_isResize = true;
if (current.type == EventType.MouseUp)
_isResize = false;
if (_isResize && current.type == EventType.MouseDrag)
{
var targetValue = _lockMode == SplitMode.Vertical
? current.mousePosition.x
: current.mousePosition.y;
var diffValue = _lockMode == SplitMode.Vertical ? rect.width : rect.height;
_ratio = targetValue / diffValue;
}
else if (current.type != EventType.Layout && Event.current.type != EventType.Used)
{
_ratio = targetSplitterValue * _ratio / targetSplitterValue;
}
_value = Mathf.Clamp(targetSplitterValue * _ratio, _lockValues, clampMax);
EditorGUI.DrawRect(RectOffset().Remove(_resizeRect), SPLITTER_COLOR_FREE);
if (_isResize)
_window.Repaint();
}
}
[Serializable]
public class HorizontalSplitter : Splitter
{
private static readonly RectOffset RECT_OFFSET = new RectOffset(0, 0, 7, 8);
public HorizontalSplitter(EditorWindow window, float defaultValue, float minValue, float barSize = 16)
: base(window, defaultValue, SplitMode.Horizontal, minValue, barSize)
{
}
protected override RectOffset RectOffset()
{
return RECT_OFFSET;
}
protected override Rect MainRect(Rect rect)
{
return new Rect(rect)
{
x = 0,
y = 0,
height = _value,
};
}
protected override Rect SubRect(Rect rect)
{
return new Rect(rect)
{
x = 0,
y = _value,
height = rect.height - _value,
};
}
protected override Rect BarRect(Rect rect)
{
return new Rect(rect)
{
x = 0,
y = _value - _barSize / 2,
height = _barSize,
};
}
}
[Serializable]
public class VerticalSplitter : Splitter
{
private static readonly RectOffset RECT_OFFSET = new RectOffset(0, 0, 7, 8);
public VerticalSplitter(EditorWindow window, float defaultValue, float minValue, float barSize = 4)
: base(window, defaultValue, SplitMode.Vertical, minValue, barSize)
{
}
protected override RectOffset RectOffset()
{
return RECT_OFFSET;
}
protected override Rect MainRect(Rect rect)
{
return new Rect(rect)
{
x = rect.x + 0,
y = rect.y + 0,
width = _value,
};
}
protected override Rect SubRect(Rect rect)
{
return new Rect(rect)
{
x = rect.x + _value,
y = rect.y + 0,
width = rect.width - _value,
};
}
protected override Rect BarRect(Rect rect)
{
return new Rect(rect)
{
x = rect.x + _value - _barSize / 2,
y = rect.y + 0,
width = _barSize,
};
}
}
}

View File

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

View File

@@ -0,0 +1,144 @@
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
{
const string TITLE = "Vrm10 Mesh Utility Window";
enum Tabs
{
MeshFreeze,
MeshIntegration,
}
Tabs _tab;
public static void OpenWindow()
{
var window =
(Vrm10MeshUtilityDialog)EditorWindow.GetWindow(typeof(Vrm10MeshUtilityDialog));
window.titleContent = new GUIContent(TITLE);
window.Show();
}
private void Validate()
{
_validations.Clear();
if (_exportTarget == null)
{
_validations.Add(Validation.Error("set vrm1"));
return;
}
if (_exportTarget.GetComponent<Vrm10Instance>() == null)
{
_validations.Add(Validation.Error("target is not vrm1"));
return;
}
}
bool IsValid => !_validations.Any(v => !v.CanExport);
Vector2 _scrollPos;
List<Validation> _validations = new List<Validation>();
GameObject _exportTarget;
MeshIntegrationAndSplit _meshIntegration;
void OnEnable()
{
_meshIntegration = new MeshIntegrationAndSplit(this);
}
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)
{
_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.MeshFreeze:
{
if (MeshBakeGui())
{
modified = true;
}
break;
}
case Tabs.MeshIntegration:
{
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)
{
// Show Result ?
// Close();
// GUIUtility.ExitGUI();
Debug.Log("Process !");
}
}
bool MeshBakeGui()
{
EditorGUILayout.Toggle("BlendShape", false);
EditorGUILayout.Toggle("Scale", false);
EditorGUILayout.Toggle("Rotation", false);
return default;
}
bool MeshIntegrateGui()
{
EditorGUILayout.Toggle("FirstPerson == AUTO の生成", false);
EditorGUILayout.Toggle("Separate by BlendShape", false);
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 - 30
};
_meshIntegration.OnGui(rect);
return default;
}
}
}

View File

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

View File

@@ -1,3 +1,4 @@
using UniGLTF.MeshUtility;
using UnityEditor;
namespace UniVRM10
@@ -11,6 +12,9 @@ namespace UniVRM10
[MenuItem(UserMenuPrefix + "/Export VRM-1.0", priority = 1)]
private static void OpenExportDialog() => VRM10ExportDialog.Open();
[MenuItem(UserMenuPrefix + "/MeshUtility", priority = 2)]
private static void OpenMeshUtility() => Vrm10MeshUtilityDialog.OpenWindow();
[MenuItem(ExperimentalMenuPrefix + "/Convert BVH to VRM-Animation", priority = 100)]
private static void ConvertVrmAnimation() => VrmAnimationMenu.BvhToVrmAnimationMenu();