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