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