using System.Collections.Generic; using System.Linq; using UnityEngine; namespace UniVRM10 { /// /// ブレンドシェイプを蓄えてまとめて適用するクラス /// class ExpressionMerger { /// /// Key から Expression を得る /// Dictionary m_clipMap; public IEnumerable ExpressionKeys => m_clipMap.Keys; /// /// Expression のWeightを記録する /// Dictionary m_valueMap; MorphTargetBindingMerger m_morphTargetBindingMerger; MaterialValueBindingMerger m_materialValueBindingMerger; public ExpressionMerger(IEnumerable clips, Transform root) { m_clipMap = clips.ToDictionary(x => ExpressionKey.CreateFromClip(x), x => x); m_valueMap = new Dictionary(); m_morphTargetBindingMerger = new MorphTargetBindingMerger(m_clipMap, root); m_materialValueBindingMerger = new MaterialValueBindingMerger(m_clipMap, root); } /// /// 蓄積した値を適用する /// public void Apply() { m_morphTargetBindingMerger.Apply(); m_materialValueBindingMerger.Apply(); } /// /// まとめて反映する。1フレームに1回呼び出されることを想定 /// /// public void SetValues(IEnumerable> values) { foreach (var kv in values) { AccumulateValue(kv.Key, kv.Value); } } /// /// 即時に反映しない。後にApplyによって反映する /// /// /// public void AccumulateValue(ExpressionKey key, float value) { m_valueMap[key] = value; VRM10Expression clip; if (!m_clipMap.TryGetValue(key, out clip)) { return; } if (clip.IsBinary) { value = Mathf.Round(value); } m_morphTargetBindingMerger.AccumulateValue(clip, value); m_materialValueBindingMerger.AccumulateValue(clip, value); } public VRM10Expression GetClip(ExpressionKey key) { if (m_clipMap.ContainsKey(key)) { return m_clipMap[key]; } else { return null; } } public void RestoreMaterialInitialValues() { m_materialValueBindingMerger.RestoreMaterialInitialValues(); } } }