From 7a95cd07ab9952777e2b9b1151035fc7f758c818 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Sat, 3 Nov 2018 16:14:13 +0900 Subject: [PATCH] Cleanup BlendShapeMerger. Removed BlendShapeMerger.Clear --- Scripts/BlendShape/BlendShapeBindingMerger.cs | 105 ++++++++ .../BlendShapeBindingMerger.cs.meta | 12 + Scripts/BlendShape/BlendShapeMerger.cs | 229 ++---------------- .../Editor/BlendShapeClipEditorHelper.cs | 6 + .../BlendShape/MaterialValueBindingMerger.cs | 169 +++++++++++++ .../MaterialValueBindingMerger.cs.meta | 12 + Scripts/BlendShape/VRMBlendShapeProxy.cs | 2 + 7 files changed, 322 insertions(+), 213 deletions(-) create mode 100644 Scripts/BlendShape/BlendShapeBindingMerger.cs create mode 100644 Scripts/BlendShape/BlendShapeBindingMerger.cs.meta create mode 100644 Scripts/BlendShape/MaterialValueBindingMerger.cs create mode 100644 Scripts/BlendShape/MaterialValueBindingMerger.cs.meta diff --git a/Scripts/BlendShape/BlendShapeBindingMerger.cs b/Scripts/BlendShape/BlendShapeBindingMerger.cs new file mode 100644 index 000000000..e2126878d --- /dev/null +++ b/Scripts/BlendShape/BlendShapeBindingMerger.cs @@ -0,0 +1,105 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace VRM +{ + /// + /// A.Value * A.Weight + B.Value * B.Weight ... + /// + class BlendShapeBindingMerger + { + /// + /// BlendShapeの適用値を蓄積する + /// + /// + /// + /// + Dictionary m_blendShapeValueMap = new Dictionary(); + + /// + /// + /// + /// + Dictionary> m_blendShapeSetterMap = new Dictionary>(); + + public BlendShapeBindingMerger(Dictionary clipMap, Transform root) + { + foreach (var kv in clipMap) + { + foreach (var binding in kv.Value.Values) + { + if (!m_blendShapeSetterMap.ContainsKey(binding)) + { + var _target = root.Find(binding.RelativePath); + SkinnedMeshRenderer target = null; + if (_target != null) + { + target = _target.GetComponent(); + } + if (target != null) + { + if (binding.Index >= 0 && binding.Index < target.sharedMesh.blendShapeCount) + { + m_blendShapeSetterMap.Add(binding, x => + { + target.SetBlendShapeWeight(binding.Index, x); + }); + } + else + { + Debug.LogWarningFormat("Invalid blendshape binding: {0}: {1}", target.name, binding); + } + + } + else + { + Debug.LogWarningFormat("SkinnedMeshRenderer: {0} not found", binding.RelativePath); + } + } + } + } + } + + public void ImmediatelySetValue(BlendShapeClip clip, float value) + { + foreach (var binding in clip.Values) + { + Action setter; + if (m_blendShapeSetterMap.TryGetValue(binding, out setter)) + { + setter(binding.Weight * value); + } + } + } + + public void AccumulateValue(BlendShapeClip clip, float value) + { + foreach (var binding in clip.Values) + { + float acc; + if (m_blendShapeValueMap.TryGetValue(binding, out acc)) + { + m_blendShapeValueMap[binding] = acc + binding.Weight * value; + } + else + { + m_blendShapeValueMap[binding] = binding.Weight * value; + } + } + } + + public void Apply() + { + foreach (var kv in m_blendShapeValueMap) + { + Action setter; + if (m_blendShapeSetterMap.TryGetValue(kv.Key, out setter)) + { + setter(kv.Value); + } + } + m_blendShapeValueMap.Clear(); + } + } +} \ No newline at end of file diff --git a/Scripts/BlendShape/BlendShapeBindingMerger.cs.meta b/Scripts/BlendShape/BlendShapeBindingMerger.cs.meta new file mode 100644 index 000000000..29c3d8446 --- /dev/null +++ b/Scripts/BlendShape/BlendShapeBindingMerger.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: ca4c8446451eeed46b1598db9e08bb73 +timeCreated: 1541229189 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/BlendShape/BlendShapeMerger.cs b/Scripts/BlendShape/BlendShapeMerger.cs index 8c88b41fe..5949751db 100644 --- a/Scripts/BlendShape/BlendShapeMerger.cs +++ b/Scripts/BlendShape/BlendShapeMerger.cs @@ -7,161 +7,38 @@ using UnityEngine; namespace VRM { + /// /// ブレンドシェイプを蓄えてまとめて適用するクラス /// class BlendShapeMerger { /// - /// KeyからBlendShapeClipを得る + /// Key からBlendShapeClipを得る /// Dictionary m_clipMap; /// - /// BlendShapeのWeightを蓄積する + /// BlendShape のWeightを記録する /// Dictionary m_valueMap; - /// - /// 名前とmaterialのマッピング - /// - Dictionary m_materialMap; + BlendShapeBindingMerger m_blendShapeBindingMerger; - /// - /// BlendShapeの適用値を蓄積する - /// - /// - /// - /// - Dictionary m_blendShapeValueMap = new Dictionary(); + MaterialValueBindingMerger m_materialValueBindingMerger; - /// - /// - /// - /// - Dictionary> m_blendShapeSetterMap = new Dictionary>(); - - /// - /// MaterialValueの適用値を蓄積する - /// - /// - /// - /// - Dictionary m_materialValueMap = new Dictionary(); - - Dictionary> m_materialSetterMap = new Dictionary>(); public BlendShapeMerger(IEnumerable clips, Transform root) { - m_materialMap = new Dictionary(); - foreach (var x in root.Traverse()) - { - var renderer = x.GetComponent(); - if (renderer != null) - { - foreach (var y in renderer.sharedMaterials.Where(y => y != null)) - { - if (!string.IsNullOrEmpty(y.name)) - { - if (!m_materialMap.ContainsKey(y.name)) - { - m_materialMap.Add(y.name, y); - } - } - } - } - } - m_clipMap = clips.ToDictionary(x => BlendShapeKey.CreateFrom(x), x => x); m_valueMap = new Dictionary(); - foreach (var kv in m_clipMap) - { - foreach (var binding in kv.Value.Values) - { - if (!m_blendShapeSetterMap.ContainsKey(binding)) - { - var _target = root.Find(binding.RelativePath); - SkinnedMeshRenderer target = null; - if (_target != null) - { - target = _target.GetComponent(); - } - if (target != null) - { - if (binding.Index >= 0 && binding.Index < target.sharedMesh.blendShapeCount) - { - m_blendShapeSetterMap.Add(binding, x => - { - target.SetBlendShapeWeight(binding.Index, x); - }); - } - else - { - Debug.LogWarningFormat("Invalid blendshape binding: {0}: {1}", target.name, binding); - } - - } - else - { - Debug.LogWarningFormat("SkinnedMeshRenderer: {0} not found", binding.RelativePath); - } - } - } - - foreach (var binding in kv.Value.MaterialValues) - { - if (!m_materialSetterMap.ContainsKey(binding)) - { - Material target; - if (m_materialMap.TryGetValue(binding.MaterialName, out target)) - { - if (binding.ValueName.EndsWith("_ST_S")) - { - var valueName = binding.ValueName.Substring(0, binding.ValueName.Length - 2); - Action setter = value => - { - var propValue = binding.BaseValue + (binding.TargetValue - binding.BaseValue) * value; - var src = target.GetVector(valueName); - src.x = propValue.x; // horizontal only - src.z = propValue.z; // horizontal only - target.SetVector(valueName, src); - }; - m_materialSetterMap.Add(binding, setter); - } - else if (binding.ValueName.EndsWith("_ST_T")) - { - var valueName = binding.ValueName.Substring(0, binding.ValueName.Length - 2); - Action setter = value => - { - var propValue = binding.BaseValue + (binding.TargetValue - binding.BaseValue) * value; - var src = target.GetVector(valueName); - src.y = propValue.y; // vertical only - src.w = propValue.w; // vertical only - target.SetVector(valueName, src); - }; - m_materialSetterMap.Add(binding, setter); - } - else - { - Action vec4Setter = x => - { - var propValue = binding.BaseValue + (binding.TargetValue - binding.BaseValue) * x; - target.SetColor(binding.ValueName, propValue); - }; - m_materialSetterMap.Add(binding, vec4Setter); - } - } - else - { - Debug.LogWarningFormat("material: {0} not found", binding.MaterialName); - } - } - } - } + m_blendShapeBindingMerger = new BlendShapeBindingMerger(m_clipMap, root); + m_materialValueBindingMerger = new MaterialValueBindingMerger(m_clipMap, root); } + /* public void Clear() { foreach (var kv in m_valueMap.ToArray()) @@ -170,31 +47,15 @@ namespace VRM } Apply(); } + */ /// /// 蓄積した値を適用する /// public void Apply() { - foreach (var kv in m_blendShapeValueMap) - { - Action setter; - if (m_blendShapeSetterMap.TryGetValue(kv.Key, out setter)) - { - setter(kv.Value); - } - } - m_blendShapeValueMap.Clear(); - - foreach (var kv in m_materialValueMap) - { - Action setter; - if (m_materialSetterMap.TryGetValue(kv.Key, out setter)) - { - setter(kv.Value); - } - } - m_materialValueMap.Clear(); + m_blendShapeBindingMerger.Apply(); + m_materialValueBindingMerger.Apply(); } /// @@ -230,33 +91,8 @@ namespace VRM value = Mathf.Round(value); } - foreach (var binding in clip.Values) - { - // 積算 - float acc; - if (m_blendShapeValueMap.TryGetValue(binding, out acc)) - { - m_blendShapeValueMap[binding] = acc + binding.Weight * value; - } - else - { - m_blendShapeValueMap[binding] = binding.Weight * value; - } - } - - foreach (var binding in clip.MaterialValues) - { - // 積算 - float acc; - if (m_materialValueMap.TryGetValue(binding, out acc)) - { - m_materialValueMap[binding] = acc + value; - } - else - { - m_materialValueMap[binding] = value; - } - } + m_blendShapeBindingMerger.AccumulateValue(clip, value); + m_materialValueBindingMerger.AccumulateValue(clip, value); } /// @@ -279,23 +115,8 @@ namespace VRM value = Mathf.Round(value); } - foreach (var binding in clip.Values) - { - Action setter; - if (m_blendShapeSetterMap.TryGetValue(binding, out setter)) - { - setter(binding.Weight * value); - } - } - - foreach (var binding in clip.MaterialValues) - { - Action setter; - if (m_materialSetterMap.TryGetValue(binding, out setter)) - { - setter(value); - } - } + m_blendShapeBindingMerger.ImmediatelySetValue(clip, value); + m_materialValueBindingMerger.ImmediatelySetValue(clip, value); } public void SetValue(BlendShapeKey key, float value, bool replace) @@ -322,25 +143,7 @@ namespace VRM public void RestoreMaterialInitialValues(IEnumerable clips) { - if (m_materialMap != null) - { - foreach (var x in clips) - { - foreach (var y in x.MaterialValues) - { - // restore values - Material material; - if (m_materialMap.TryGetValue(y.MaterialName, out material)) - { - material.SetColor(y.ValueName, y.BaseValue); - } - else - { - Debug.LogWarningFormat("{0} not found", y.MaterialName); - } - } - } - } + m_materialValueBindingMerger.RestoreMaterialInitialValues(clips); } } } diff --git a/Scripts/BlendShape/Editor/BlendShapeClipEditorHelper.cs b/Scripts/BlendShape/Editor/BlendShapeClipEditorHelper.cs index 57627ba75..9b5010968 100644 --- a/Scripts/BlendShape/Editor/BlendShapeClipEditorHelper.cs +++ b/Scripts/BlendShape/Editor/BlendShapeClipEditorHelper.cs @@ -7,6 +7,9 @@ namespace VRM { public static class BlendShapeClipEditorHelper { + /// + /// BlendShape List のElement描画 + /// public static bool DrawBlendShapeBinding(Rect position, SerializedProperty property, PreviewSceneManager scene) { @@ -41,6 +44,9 @@ namespace VRM return changed; } + /// + /// Material List のElement描画 + /// public static bool DrawMaterialValueBinding(Rect position, SerializedProperty property, PreviewSceneManager scene) { diff --git a/Scripts/BlendShape/MaterialValueBindingMerger.cs b/Scripts/BlendShape/MaterialValueBindingMerger.cs new file mode 100644 index 000000000..31c2559a4 --- /dev/null +++ b/Scripts/BlendShape/MaterialValueBindingMerger.cs @@ -0,0 +1,169 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; +using UniGLTF; + +namespace VRM +{ + /// + /// Base + (A.Target - Base) * A.Weight + (B.Target - Base) * B.Weight ... + /// + class MaterialValueBindingMerger + { + /// + /// 名前とmaterialのマッピング + /// + Dictionary m_materialMap; + + /// + /// MaterialValueの適用値を蓄積する + /// + /// + /// + /// + Dictionary m_materialValueMap = new Dictionary(); + + Dictionary> m_materialSetterMap = new Dictionary>(); + + public MaterialValueBindingMerger(Dictionary clipMap, Transform root) + { + m_materialMap = new Dictionary(); + foreach (var x in root.Traverse()) + { + var renderer = x.GetComponent(); + if (renderer != null) + { + foreach (var y in renderer.sharedMaterials.Where(y => y != null)) + { + if (!string.IsNullOrEmpty(y.name)) + { + if (!m_materialMap.ContainsKey(y.name)) + { + m_materialMap.Add(y.name, y); + } + } + } + } + } + + foreach (var kv in clipMap) + { + foreach (var binding in kv.Value.MaterialValues) + { + if (!m_materialSetterMap.ContainsKey(binding)) + { + Material target; + if (m_materialMap.TryGetValue(binding.MaterialName, out target)) + { + if (binding.ValueName.EndsWith("_ST_S")) + { + var valueName = binding.ValueName.Substring(0, binding.ValueName.Length - 2); + Action setter = value => + { + var propValue = binding.BaseValue + (binding.TargetValue - binding.BaseValue) * value; + var src = target.GetVector(valueName); + src.x = propValue.x; // horizontal only + src.z = propValue.z; // horizontal only + target.SetVector(valueName, src); + }; + m_materialSetterMap.Add(binding, setter); + } + else if (binding.ValueName.EndsWith("_ST_T")) + { + var valueName = binding.ValueName.Substring(0, binding.ValueName.Length - 2); + Action setter = value => + { + var propValue = binding.BaseValue + (binding.TargetValue - binding.BaseValue) * value; + var src = target.GetVector(valueName); + src.y = propValue.y; // vertical only + src.w = propValue.w; // vertical only + target.SetVector(valueName, src); + }; + m_materialSetterMap.Add(binding, setter); + } + else + { + Action vec4Setter = x => + { + var propValue = binding.BaseValue + (binding.TargetValue - binding.BaseValue) * x; + target.SetColor(binding.ValueName, propValue); + }; + m_materialSetterMap.Add(binding, vec4Setter); + } + } + else + { + Debug.LogWarningFormat("material: {0} not found", binding.MaterialName); + } + } + } + } + } + + public void RestoreMaterialInitialValues(IEnumerable clips) + { + if (m_materialMap != null) + { + foreach (var x in clips) + { + foreach (var y in x.MaterialValues) + { + // restore values + Material material; + if (m_materialMap.TryGetValue(y.MaterialName, out material)) + { + material.SetColor(y.ValueName, y.BaseValue); + } + else + { + Debug.LogWarningFormat("{0} not found", y.MaterialName); + } + } + } + } + } + + public void ImmediatelySetValue(BlendShapeClip clip, float value) + { + foreach (var binding in clip.MaterialValues) + { + Action setter; + if (m_materialSetterMap.TryGetValue(binding, out setter)) + { + setter(value); + } + } + } + + public void AccumulateValue(BlendShapeClip clip, float value) + { + foreach (var binding in clip.MaterialValues) + { + // 積算 + float acc; + if (m_materialValueMap.TryGetValue(binding, out acc)) + { + m_materialValueMap[binding] = acc + value; + } + else + { + m_materialValueMap[binding] = value; + } + } + } + + public void Apply() + { + foreach (var kv in m_materialValueMap) + { + Action setter; + if (m_materialSetterMap.TryGetValue(kv.Key, out setter)) + { + setter(kv.Value); + } + } + m_materialValueMap.Clear(); + } + } +} diff --git a/Scripts/BlendShape/MaterialValueBindingMerger.cs.meta b/Scripts/BlendShape/MaterialValueBindingMerger.cs.meta new file mode 100644 index 000000000..53929f073 --- /dev/null +++ b/Scripts/BlendShape/MaterialValueBindingMerger.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 4ccc88d77d5d1e74499d053083ade08d +timeCreated: 1541229189 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/BlendShape/VRMBlendShapeProxy.cs b/Scripts/BlendShape/VRMBlendShapeProxy.cs index 9d07bd519..9725b0347 100644 --- a/Scripts/BlendShape/VRMBlendShapeProxy.cs +++ b/Scripts/BlendShape/VRMBlendShapeProxy.cs @@ -159,6 +159,7 @@ namespace VRM } } + /* /// /// Clear all blendShape values /// @@ -169,6 +170,7 @@ namespace VRM m_merger.Clear(); } } + */ /// /// Apply blendShape values that use SetValue apply=false