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(); } } }