diff --git a/Scripts/BlendShape/BlendShapeClip.cs b/Scripts/BlendShape/BlendShapeClip.cs index 45a4120bb..7163ede38 100644 --- a/Scripts/BlendShape/BlendShapeClip.cs +++ b/Scripts/BlendShape/BlendShapeClip.cs @@ -15,12 +15,10 @@ namespace VRM [Serializable] public struct MaterialValueBinding { - public String RelativePath; - public int Index; - public string ValueName; + public String MaterialName; + public String ValueName; public Vector4 TargetValue; - - public Vector4 BaseValue; // <- Get From RelativePath/Materials[Index][ValueName] + public Vector4 BaseValue; } [CreateAssetMenu(menuName = "VRM/BlendShapeClip")] @@ -56,6 +54,7 @@ namespace VRM } } + /* if (MaterialValues != null) { foreach (var x in MaterialValues) @@ -73,6 +72,7 @@ namespace VRM } } } + */ } public static BlendShapeClip Create(BlendShapePreset preset) diff --git a/Scripts/BlendShape/Editor/BlendShapeAvatarEditor.cs b/Scripts/BlendShape/Editor/BlendShapeAvatarEditor.cs index 7c2f30b80..042c0a51b 100644 --- a/Scripts/BlendShape/Editor/BlendShapeAvatarEditor.cs +++ b/Scripts/BlendShape/Editor/BlendShapeAvatarEditor.cs @@ -46,7 +46,7 @@ namespace VRM m_currentClip = value; //ClearBlendShape(); - Bake(m_currentClip.Values, m_currentClip.MaterialValues); + Bake(m_currentClip.Values, m_currentClip.MaterialValues, 1.0f); } } diff --git a/Scripts/BlendShape/Editor/BlendShapeClipEditor.cs b/Scripts/BlendShape/Editor/BlendShapeClipEditor.cs index 48fd7f1d5..dad5d5508 100644 --- a/Scripts/BlendShape/Editor/BlendShapeClipEditor.cs +++ b/Scripts/BlendShape/Editor/BlendShapeClipEditor.cs @@ -9,6 +9,8 @@ namespace VRM [CustomEditor(typeof(BlendShapeClip))] public class BlendShapeClipEditor : PreviewEditor { + float m_previewSlider; + #region for Editor SerializedProperty m_BlendShapeNameProp; SerializedProperty m_PresetProp; @@ -25,8 +27,10 @@ namespace VRM { base.OnEnable(); + m_previewSlider = 1.0f; + m_target = (BlendShapeClip)target; - Bake(m_target.Values, m_target.MaterialValues); + Bake(m_target.Values, m_target.MaterialValues, m_previewSlider); m_BlendShapeNameProp = serializedObject.FindProperty("BlendShapeName"); m_PresetProp = serializedObject.FindProperty("Preset"); @@ -63,9 +67,17 @@ namespace VRM public override void OnInspectorGUI() { base.OnInspectorGUI(); - m_changed = false; + EditorGUILayout.Space(); + var previewSlider= EditorGUILayout.Slider("Preview Weight", m_previewSlider, 0, 1.0f); + if (previewSlider != m_previewSlider) { + m_previewSlider = previewSlider; + m_changed = true; + } + + EditorGUILayout.Space(); + serializedObject.Update(); EditorGUILayout.PropertyField(m_BlendShapeNameProp, true); @@ -81,7 +93,7 @@ namespace VRM if (m_changed && PreviewSceneManager!=null) { - PreviewSceneManager.Bake(m_target.Values, m_target.MaterialValues); + PreviewSceneManager.Bake(m_target.Values, m_target.MaterialValues, m_previewSlider); } } @@ -136,49 +148,46 @@ namespace VRM var y = position.y; var rect = new Rect(position.x, y, position.width, height); - int pathIndex; - if (StringPopup(rect, property.FindPropertyRelative("RelativePath"), scene.RendererPathList, out pathIndex)) - { - changed = true; - } - - y += height; - rect = new Rect(position.x, y, position.width, height); int materialIndex; - if (IntPopup(rect, property.FindPropertyRelative("Index"), scene.GetMaterialNames(pathIndex), out materialIndex)) + if (StringPopup(rect, property.FindPropertyRelative("MaterialName"), scene.MaterialNames, out materialIndex)) { changed = true; } - y += height; - rect = new Rect(position.x, y, position.width, height); - int propIndex; - if (StringPopup(rect, property.FindPropertyRelative("ValueName"), scene.GetMaterialPropNames(pathIndex, materialIndex), out propIndex)) + if (materialIndex >= 0) { - changed = true; - } - - if (propIndex >= 0) - { - var propTypes = scene.GetMaterialPropTypes(pathIndex, materialIndex); - if (propTypes != null && propIndex < propTypes.Length) + var materialItem = scene.GetMaterialItem(scene.MaterialNames[materialIndex]); + if (materialItem != null) { - switch (propTypes[propIndex]) + y += height; + rect = new Rect(position.x, y, position.width, height); + int propIndex; + if (StringPopup(rect, property.FindPropertyRelative("ValueName"), materialItem.PropNames, out propIndex)) { - case ShaderUtil.ShaderPropertyType.Color: - { - var baseValues= scene.GetMaterialPropBaseValues(pathIndex, materialIndex); - property.FindPropertyRelative("BaseValue").vector4Value = baseValues[propIndex]; + changed = true; + } - // max - y += height; - rect = new Rect(position.x, y, position.width, height); - if (ColorProp(rect, property.FindPropertyRelative("TargetValue"))) - { - changed = true; - } + if (propIndex >= 0) + { + var propItem = materialItem.PropMap[materialItem.PropNames[propIndex]]; + { + switch (propItem.PropertyType) + { + case ShaderUtil.ShaderPropertyType.Color: + { + property.FindPropertyRelative("BaseValue").vector4Value = propItem.DefaultValues; + + // max + y += height; + rect = new Rect(position.x, y, position.width, height); + if (ColorProp(rect, property.FindPropertyRelative("TargetValue"))) + { + changed = true; + } + } + break; } - break; + } } } } diff --git a/Scripts/BlendShape/Editor/PreviewEditor.cs b/Scripts/BlendShape/Editor/PreviewEditor.cs index 49b44e66b..30476d1c1 100644 --- a/Scripts/BlendShape/Editor/PreviewEditor.cs +++ b/Scripts/BlendShape/Editor/PreviewEditor.cs @@ -42,11 +42,11 @@ namespace VRM } } - protected void Bake(BlendShapeBinding[] values, MaterialValueBinding[] materialValues) + protected void Bake(BlendShapeBinding[] values, MaterialValueBinding[] materialValues, float weight) { if (m_scene != null) { - m_scene.Bake(values, materialValues); + m_scene.Bake(values, materialValues, weight); } } diff --git a/Scripts/BlendShape/MeshPreviewItem.cs b/Scripts/BlendShape/MeshPreviewItem.cs index b422ab223..eed305aff 100644 --- a/Scripts/BlendShape/MeshPreviewItem.cs +++ b/Scripts/BlendShape/MeshPreviewItem.cs @@ -7,8 +7,59 @@ using System.Collections.Generic; using UnityEditor; #endif + namespace VRM { + [Serializable] + public struct PropItem + { + public ShaderUtil.ShaderPropertyType PropertyType; + public Vector4 DefaultValues; + } + + [Serializable] + public class MaterialItem + { + public Material Material { get; private set; } +#if UNITY_EDITOR + public Dictionary PropMap = new Dictionary(); + + public string[] PropNames + { + get; + private set; + } +#endif + + public static MaterialItem Create(Material material) + { + var item = new MaterialItem + { + Material = material + }; +#if UNITY_EDITOR + + var propNames = new List(); + for (int i = 0; i < ShaderUtil.GetPropertyCount(material.shader); ++i) + { + var propType = ShaderUtil.GetPropertyType(material.shader, i); + if (propType == ShaderUtil.ShaderPropertyType.Color) + { + var name = ShaderUtil.GetPropertyName(material.shader, i); + item.PropMap.Add(name, new PropItem + { + PropertyType = propType, + DefaultValues = material.GetColor(name), + }); + propNames.Add(name); + } + } + item.PropNames = propNames.ToArray(); +#endif + return item; + } + } + [Serializable] public class MeshPreviewItem { @@ -35,77 +86,16 @@ namespace VRM get; private set; } + public int BlendShapeCount { get { return BlendShapeNames.Length; } } - Material[] m_materials; public Material[] Materials { - get { return m_materials; } - private set - { - m_materials = value; - m_materialNames = value.Select(x => x.name).ToArray(); - -#if UNITY_EDITOR - int i = 0; - foreach (var x in value) - { - var propNames = Enumerable.Range(0, ShaderUtil.GetPropertyCount(x.shader)) - .Where(y => ShaderUtil.GetPropertyType(x.shader, y) == ShaderUtil.ShaderPropertyType.Color) - .Select(y => ShaderUtil.GetPropertyName(x.shader, y)) - .ToArray(); - m_materialPropNamesList.Add(propNames); - - var propTypes = Enumerable.Range(0, ShaderUtil.GetPropertyCount(x.shader)) - .Select(y => ShaderUtil.GetPropertyType(x.shader, y)) - .Where(y => y == ShaderUtil.ShaderPropertyType.Color) - .ToArray(); - m_materialPropTypesList.Add(propTypes); - - var propValues = propNames.Select(y => (Vector4)x.GetColor(y)).ToArray(); - m_materialPropDefaultValueList.Add(propValues); - } -#endif - } - } - - string[] m_materialNames; - public string[] MaterialsNames - { - get { return m_materialNames; } - } - - List m_materialPropNamesList = new List(); - public string[] GetMaterialPropNames(int materialIndex) - { - if(m_materialPropNamesList==null || materialIndex<0 || materialIndex >= m_materialPropNamesList.Count) - { - return null; - } - return m_materialPropNamesList[materialIndex]; - } - - List m_materialPropTypesList = new List(); - public ShaderUtil.ShaderPropertyType[] GetMaterialPropTypes(int materialIndex) - { - if (m_materialPropTypesList == null || materialIndex < 0 || materialIndex >= m_materialPropTypesList.Count) - { - return null; - } - return m_materialPropTypesList[materialIndex]; - } - - List m_materialPropDefaultValueList = new List(); - public Vector4[] GetMaterialPropBaseValues(int materialIndex) - { - if (m_materialPropDefaultValueList == null || materialIndex < 0 || materialIndex >= m_materialPropDefaultValueList.Count) - { - return null; - } - return m_materialPropDefaultValueList[materialIndex]; + get; + private set; } Transform m_transform; @@ -118,17 +108,17 @@ namespace VRM get { return m_transform.rotation; } } - MeshPreviewItem(string path, Transform transform) + MeshPreviewItem(string path, Transform transform, Material[] materials) { Path = path; m_transform = transform; + Materials = materials; } - public void Bake(BlendShapeBinding[] values, MaterialValueBinding[] materialValues) + public void Bake(BlendShapeBinding[] values, float weight) { - if (SkinnedMeshRenderer == null) return; - - if (values != null) + // Update baked mesh + if (SkinnedMeshRenderer != null && values != null) { // clear for (int i = 0; i < BlendShapeCount; ++i) @@ -140,47 +130,19 @@ namespace VRM { if (x.RelativePath == Path) { - SkinnedMeshRenderer.SetBlendShapeWeight(x.Index, x.Weight); - } - } - } - - if (materialValues != null && m_materialPropNamesList!=null) - { - // clear - for (int i = 0; i < Materials.Length; ++i) - { - var names = m_materialPropNamesList[i]; - var defaultValues = m_materialPropDefaultValueList[i]; - for (int j = 0; j < names.Length; ++j) - { - Materials[i].SetColor(names[j], defaultValues[j]); + SkinnedMeshRenderer.SetBlendShapeWeight(x.Index, x.Weight * weight); } } - foreach (var x in materialValues) - { - if(x.RelativePath == Path) - { - var material = Materials[x.Index]; - material.SetColor(x.ValueName, x.TargetValue); - } - } - } - - SkinnedMeshRenderer.BakeMesh(Mesh); - } - - public void Clean() - { - foreach (var x in Materials) - { - UnityEngine.Object.DestroyImmediate(x); + SkinnedMeshRenderer.BakeMesh(Mesh); } } - public static MeshPreviewItem Create(Transform t, Transform root, Func getOrCreateMaterial) + public static MeshPreviewItem Create(Transform t, Transform root, + Func getOrCreateMaterial) { + //Debug.Log("create"); + var meshFilter = t.GetComponent(); var meshRenderer = t.GetComponent(); var skinnedMeshRenderer = t.GetComponent(); @@ -188,10 +150,9 @@ namespace VRM { // copy meshRenderer.sharedMaterials = meshRenderer.sharedMaterials.Select(x => getOrCreateMaterial(x)).ToArray(); - return new MeshPreviewItem(t.RelativePathFrom(root), t) + return new MeshPreviewItem(t.RelativePathFrom(root), t, meshRenderer.sharedMaterials) { - Mesh = meshFilter.sharedMesh, - Materials = meshRenderer.sharedMaterials + Mesh = meshFilter.sharedMesh }; } else if (skinnedMeshRenderer != null) @@ -202,20 +163,18 @@ namespace VRM { // bake required var sharedMesh = skinnedMeshRenderer.sharedMesh; - return new MeshPreviewItem(t.RelativePathFrom(root), t) + return new MeshPreviewItem(t.RelativePathFrom(root), t, skinnedMeshRenderer.sharedMaterials) { SkinnedMeshRenderer = skinnedMeshRenderer, Mesh = new Mesh(), // for bake - BlendShapeNames = Enumerable.Range(0, sharedMesh.blendShapeCount).Select(x => sharedMesh.GetBlendShapeName(x)).ToArray(), - Materials = skinnedMeshRenderer.sharedMaterials + BlendShapeNames = Enumerable.Range(0, sharedMesh.blendShapeCount).Select(x => sharedMesh.GetBlendShapeName(x)).ToArray() }; } else { - return new MeshPreviewItem(t.RelativePathFrom(root), t) + return new MeshPreviewItem(t.RelativePathFrom(root), t, skinnedMeshRenderer.sharedMaterials) { Mesh = skinnedMeshRenderer.sharedMesh, - Materials = skinnedMeshRenderer.sharedMaterials }; } } diff --git a/Scripts/BlendShape/PreviewSceneManager.cs b/Scripts/BlendShape/PreviewSceneManager.cs index 07bc8e0eb..da273fa02 100644 --- a/Scripts/BlendShape/PreviewSceneManager.cs +++ b/Scripts/BlendShape/PreviewSceneManager.cs @@ -68,9 +68,9 @@ namespace VRM public void Clean() { - foreach(var x in m_meshes) + foreach (var kv in m_materialMap) { - x.Clean(); + UnityEngine.Object.DestroyImmediate(kv.Value.Material); } } @@ -89,15 +89,21 @@ namespace VRM } */ + var materialNames = new List(); var map = new Dictionary(); Func getOrCreateMaterial = src => { if (src == null) return null; + if (string.IsNullOrEmpty(src.name)) return null; // ! + Material dst; if(!map.TryGetValue(src, out dst)) { dst = new Material(src); map.Add(src, dst); + + materialNames.Add(src.name); + m_materialMap.Add(src.name, MaterialItem.Create(dst)); } return dst; }; @@ -107,6 +113,8 @@ namespace VRM .Where(x => x != null) .ToArray() ; + MaterialNames = materialNames.ToArray(); + m_blendShapeMeshes = m_meshes .Where(x => x.SkinnedMeshRenderer != null && x.SkinnedMeshRenderer.sharedMesh.blendShapeCount>0) @@ -137,6 +145,14 @@ namespace VRM } } + public string[] MaterialNames + { + get; + private set; + } + + Dictionary m_materialMap = new Dictionary(); + string[] m_rendererPathList; public string[] RendererPathList { @@ -160,62 +176,18 @@ namespace VRM return null; } - public string[] GetMaterialNames(int rendererIndex) + public MaterialItem GetMaterialItem(string materialName) { - if (rendererIndex >= 0 && rendererIndex < m_meshes.Length) - { - return m_meshes[rendererIndex].MaterialsNames; - } - return null; - } - - public string[] GetMaterialPropNames(int rendererIndex, int materialIndex) - { - if(rendererIndex<0 || rendererIndex >= m_meshes.Length) - { + MaterialItem item; + if(!m_materialMap.TryGetValue(materialName, out item)){ return null; } - if(materialIndex<0 || materialIndex >= m_meshes[rendererIndex].MaterialsNames.Length) - { - return null; - } - - return m_meshes[rendererIndex].GetMaterialPropNames(materialIndex); - } - - public ShaderUtil.ShaderPropertyType[] GetMaterialPropTypes(int rendererIndex, int materialIndex) - { - if (rendererIndex < 0 || rendererIndex >= m_meshes.Length) - { - return null; - } - - if (materialIndex < 0 || materialIndex >= m_meshes[rendererIndex].MaterialsNames.Length) - { - return null; - } - - return m_meshes[rendererIndex].GetMaterialPropTypes(materialIndex); - } - - public Vector4[] GetMaterialPropBaseValues(int rendererIndex, int materialIndex) - { - if (rendererIndex < 0 || rendererIndex >= m_meshes.Length) - { - return null; - } - - if (materialIndex < 0 || materialIndex >= m_meshes[rendererIndex].MaterialsNames.Length) - { - return null; - } - - return m_meshes[rendererIndex].GetMaterialPropBaseValues(materialIndex); + return item; } Bounds m_bounds; - public void Bake(BlendShapeBinding[] values=null, MaterialValueBinding[] materialValues=null) + public void Bake(BlendShapeBinding[] values=null, MaterialValueBinding[] materialValues=null, float weight=1.0f) { //Debug.LogFormat("Bake"); m_bounds = default(Bounds); @@ -223,10 +195,40 @@ namespace VRM { foreach (var x in m_meshes) { - x.Bake(values, materialValues); + x.Bake(values, weight); m_bounds.Expand(x.Mesh.bounds.size); } } + + // Udpate Material + if (materialValues != null && m_materialMap != null) + { + // clear + Debug.LogFormat("clear material"); + foreach (var kv in m_materialMap) + { + foreach (var _kv in kv.Value.PropMap) + { + kv.Value.Material.SetColor(_kv.Key, _kv.Value.DefaultValues); + } + } + + foreach (var x in materialValues) + { + MaterialItem item; + if (m_materialMap.TryGetValue(x.MaterialName, out item)) + { + Debug.Log("set material"); + PropItem prop; + if (item.PropMap.TryGetValue(x.ValueName, out prop)) + { + var value = x.BaseValue + (x.TargetValue - x.BaseValue) * weight; + item.Material.SetColor(x.ValueName, value); + } + } + } + } + } /*