diff --git a/Scripts/BlendShape/Editor/VRMBlnedShapeProxyEditor.cs b/Scripts/BlendShape/Editor/VRMBlnedShapeProxyEditor.cs index e019a44f8..ecf259e5b 100644 --- a/Scripts/BlendShape/Editor/VRMBlnedShapeProxyEditor.cs +++ b/Scripts/BlendShape/Editor/VRMBlnedShapeProxyEditor.cs @@ -177,7 +177,8 @@ namespace VRM ClearBlendShape(); if (Application.isPlaying) { - m_target.Reload(); + m_target.Restore(); + m_target.Apply(); } else { diff --git a/Scripts/BlendShape/VRMBlendShapeProxy.cs b/Scripts/BlendShape/VRMBlendShapeProxy.cs index 8e597826d..9da07c939 100644 --- a/Scripts/BlendShape/VRMBlendShapeProxy.cs +++ b/Scripts/BlendShape/VRMBlendShapeProxy.cs @@ -4,89 +4,234 @@ using System.Linq; using UnityEngine; + namespace VRM { + [DisallowMultipleComponent] public class VRMBlendShapeProxy : MonoBehaviour { [SerializeField] public BlendShapeAvatar BlendShapeAvatar; - Dictionary m_handlerMap; - public Dictionary CreateHandlerMap() + struct BlendShapePath { - var handlerMap = new Dictionary( - new BlendShapeKey.CustomerEqualityComparer()); - foreach (var x in BlendShapeAvatar.Clips) - { - handlerMap.Add(BlendShapeKey.CreateFrom(x), new BlendShapeClipHandler(x, transform)); - ; - } - return handlerMap; + public String RelativePath; + public int Index; } + delegate void BlendShapeSetter(float value); + + class BlendShapePathHandler + { + public BlendShapeSetter Setter; + float m_value; + + /* + public void ReplaceValue(float value) + { + m_value = value; + } + */ + + public void AddValue(float value) + { + m_value += value; + } + + public void Apply(float value) + { + Setter(value); + m_value = 0; + } + + public void Apply() + { + Setter(m_value); + m_value = 0; + } + + public void Clear() + { + m_value = 0; + Apply(); + } + } + + class BlendShapeMerger + { + Dictionary m_clipMap; + Dictionary m_valueMap; + Dictionary m_setterMap = new Dictionary(); + + public BlendShapeMerger(IEnumerable clips, Transform root) + { + m_clipMap = clips.ToDictionary(x => BlendShapeKey.CreateFrom(x), x => x, new BlendShapeKey.CustomerEqualityComparer()); + m_valueMap = new Dictionary(new BlendShapeKey.CustomerEqualityComparer()); + foreach (var kv in m_clipMap) + { + foreach (var binding in kv.Value.Values) { + + if (!m_setterMap.ContainsKey(binding)) + { + var _target = root.Find(binding.RelativePath); + SkinnedMeshRenderer target = null; + if (_target != null) + { + target = _target.GetComponent(); + } + if (target != null) + { + m_setterMap.Add(binding, new BlendShapePathHandler + { + Setter = x => + { + target.SetBlendShapeWeight(binding.Index, x); + } + }); + } + else + { + Debug.LogWarningFormat("{0} not found", binding.RelativePath); + } + } + } + } + } + + public void Clear() + { + foreach(var kv in m_setterMap) + { + kv.Value.Clear(); + } + } + + public void Restore() + { + foreach (var kv in m_valueMap.ToArray()) + { + SetValue(kv.Key, kv.Value, false); + } + } + + public void Apply() + { + foreach(var kv in m_setterMap) + { + kv.Value.Apply(); + } + } + + public void SetValue(BlendShapeKey key, float value, bool replace) + { + m_valueMap[key] = value; + + BlendShapeClip clip; + if(!m_clipMap.TryGetValue(key, out clip)) + { + return; + } + + foreach(var binding in clip.Values) + { + BlendShapePathHandler handler; + if(m_setterMap.TryGetValue(binding, out handler)) + { + if (replace) + { + // 値置き換え + //handler.ReplaceValue(); + handler.Apply(binding.Weight * value); + } + else + { + // 積算 + handler.AddValue(binding.Weight * value); + } + } + else + { + Debug.LogWarningFormat("'{0}' not found", binding); + } + } + } + + public float GetValue(BlendShapeKey key) + { + float value; + if (!m_valueMap.TryGetValue(key, out value)) + { + return 0; + } + return value; + } + } + BlendShapeMerger m_merger; + private void Update() { if (BlendShapeAvatar != null) { - if (m_handlerMap == null) + if (m_merger == null) { - m_handlerMap = CreateHandlerMap(); + m_merger = new BlendShapeMerger(BlendShapeAvatar.Clips, transform); } } } - public void Reload() + public void SetValue(BlendShapePreset key, float value, bool apply=true) { - if (BlendShapeAvatar == null) return; - - foreach (var kv in m_handlerMap) - { - SetValue(kv.Key, GetValue(kv.Key)); - } - } - - public void SetValue(BlendShapePreset key, float value) - { - SetValue(new BlendShapeKey(key), value); + SetValue(new BlendShapeKey(key), value, apply); } public float GetValue(BlendShapePreset key) { return GetValue(new BlendShapeKey(key)); } - public void SetValue(String key, float value) + public void SetValue(String key, float value, bool apply=true) { - SetValue(new BlendShapeKey(key), value); + SetValue(new BlendShapeKey(key), value, apply); } public float GetValue(String key) { return GetValue(new BlendShapeKey(key)); } - public void SetValue(BlendShapeKey key, float value) + public void SetValue(BlendShapeKey key, float value, bool apply=true) { - if (m_handlerMap == null) return; - BlendShapeClipHandler handler; - if (m_handlerMap.TryGetValue(key, out handler)) + if (m_merger != null) { - handler.Apply(value); + m_merger.SetValue(key, value, apply); } } public float GetValue(BlendShapeKey key) { - if (m_handlerMap == null) return 0; - BlendShapeClipHandler handler; - if (!m_handlerMap.TryGetValue(key, out handler)) + if (m_merger == null) { return 0; } - return handler.LastValue; + return m_merger.GetValue(key); } public void ClearKeys() { - if (m_handlerMap == null) return; - foreach(var kv in m_handlerMap) + if (m_merger != null) { - kv.Value.Apply(0); + m_merger.Clear(); + } + } + + public void Restore() + { + if (m_merger != null) + { + m_merger.Restore(); + } + } + + public void Apply() + { + if (m_merger != null) + { + m_merger.Apply(); } } } diff --git a/Scripts/Format/VRMVersion.cs b/Scripts/Format/VRMVersion.cs index 146cd50b6..0d1ac9762 100644 --- a/Scripts/Format/VRMVersion.cs +++ b/Scripts/Format/VRMVersion.cs @@ -4,11 +4,11 @@ namespace VRM public static class VRMVersion { public const int MAJOR = 0; - public const int MINOR = 10; + public const int MINOR = 11; - public const string VERSION = "0.10"; + public const string VERSION = "0.11"; - public const string DecrementMenuName = "VRM/Version(0.10) Decrement"; - public const string IncrementMenuName = "VRM/Version(0.10) Increment"; + public const string DecrementMenuName = "VRM/Version(0.11) Decrement"; + public const string IncrementMenuName = "VRM/Version(0.11) Increment"; } }