using System; using System.Collections.Generic; using System.Linq; using UniGLTF; using UnityEngine; namespace VRM { /// /// ブレンドシェイプを蓄えてまとめて適用するクラス /// public class BlendShapeMerger { /// /// Key からBlendShapeClipを得る /// Dictionary m_clipMap; /// /// BlendShape のWeightを記録する /// Dictionary m_valueMap; BlendShapeBindingMerger m_blendShapeBindingMerger; MaterialValueBindingMerger m_materialValueBindingMerger; public BlendShapeMerger(IEnumerable clips, Transform root) { m_clipMap = clips.ToDictionary(x => BlendShapeKey.CreateFromClip(x), x => x); m_valueMap = new Dictionary(); m_blendShapeBindingMerger = new BlendShapeBindingMerger(m_clipMap, root); m_materialValueBindingMerger = new MaterialValueBindingMerger(m_clipMap, root); } /* public void Clear() { foreach (var kv in m_valueMap.ToArray()) { SetValue(kv.Key, kv.Value, false); } Apply(); } */ /// /// 蓄積した値を適用する /// public void Apply() { m_blendShapeBindingMerger.Apply(); m_materialValueBindingMerger.Apply(); } /// /// まとめて反映する。1フレームに1回呼び出されることを想定 /// /// public void SetValues(IEnumerable> values) { foreach (var kv in values) { AccumulateValue(kv.Key, kv.Value); } Apply(); } /// /// 即時に反映しない。後にApplyによって反映する /// /// /// public void AccumulateValue(BlendShapeKey key, float value) { m_valueMap[key] = value; BlendShapeClip clip; if (!m_clipMap.TryGetValue(key, out clip)) { return; } if (clip.IsBinary) { value = Mathf.Round(value); } m_blendShapeBindingMerger.AccumulateValue(clip, value); m_materialValueBindingMerger.AccumulateValue(clip, value); } /// /// 即時に反映する /// /// /// public void ImmediatelySetValue(BlendShapeKey key, float value) { m_valueMap[key] = value; BlendShapeClip clip; if (!m_clipMap.TryGetValue(key, out clip)) { return; } if (clip.IsBinary) { value = Mathf.Round(value); } m_blendShapeBindingMerger.ImmediatelySetValue(clip, value); m_materialValueBindingMerger.ImmediatelySetValue(clip, value); } public void SetValue(BlendShapeKey key, float value, bool immediately) { if (immediately) { ImmediatelySetValue(key, value); } else { AccumulateValue(key, value); } } public float GetValue(BlendShapeKey key) { float value; if (!m_valueMap.TryGetValue(key, out value)) { return 0; } return value; } public void RestoreMaterialInitialValues(IEnumerable clips) { m_materialValueBindingMerger.RestoreMaterialInitialValues(clips); } } }