using System; using System.Collections.Generic; using System.Linq; using UnityEngine; namespace UniVRM10 { [Serializable] public class VRM10ControllerExpression : IDisposable { [SerializeField] public VRM10ExpressionAvatar ExpressionAvatar; bool m_ignoreBlink; bool m_ignoreLookAt; bool m_ignoreMouth; #region for CustomEditor public bool IgnoreBlink => m_ignoreBlink; public bool IgnoreLookAt => m_ignoreLookAt; public bool IgnoreMouth => m_ignoreMouth; #endregion public Dictionary expressionKeyWeights = new Dictionary(); List m_blinkExpressionKeys = new List(); List m_lookAtExpressionKeys = new List(); List m_mouthExpressionKeys = new List(); ExpressionMerger m_merger; public void Dispose() { if (m_merger != null) { m_merger.RestoreMaterialInitialValues(); } } public void OnStart(Transform transform) { if (ExpressionAvatar != null) { if (m_merger == null) { m_merger = new ExpressionMerger(ExpressionAvatar.Clips, transform); } } expressionKeyWeights = m_merger.ExpressionKeys.ToDictionary(x => x, x => 0.0f); m_blinkExpressionKeys.Add(m_merger.ExpressionKeys.FirstOrDefault(x => x.Preset == VrmLib.ExpressionPreset.Blink)); m_lookAtExpressionKeys.Add(m_merger.ExpressionKeys.FirstOrDefault(x => x.Preset == VrmLib.ExpressionPreset.LookUp)); m_lookAtExpressionKeys.Add(m_merger.ExpressionKeys.FirstOrDefault(x => x.Preset == VrmLib.ExpressionPreset.LookDown)); m_lookAtExpressionKeys.Add(m_merger.ExpressionKeys.FirstOrDefault(x => x.Preset == VrmLib.ExpressionPreset.LookLeft)); m_lookAtExpressionKeys.Add(m_merger.ExpressionKeys.FirstOrDefault(x => x.Preset == VrmLib.ExpressionPreset.LookRight)); m_mouthExpressionKeys.Add(m_merger.ExpressionKeys.FirstOrDefault(x => x.Preset == VrmLib.ExpressionPreset.Aa)); m_mouthExpressionKeys.Add(m_merger.ExpressionKeys.FirstOrDefault(x => x.Preset == VrmLib.ExpressionPreset.Ih)); m_mouthExpressionKeys.Add(m_merger.ExpressionKeys.FirstOrDefault(x => x.Preset == VrmLib.ExpressionPreset.Ou)); m_mouthExpressionKeys.Add(m_merger.ExpressionKeys.FirstOrDefault(x => x.Preset == VrmLib.ExpressionPreset.Ee)); m_mouthExpressionKeys.Add(m_merger.ExpressionKeys.FirstOrDefault(x => x.Preset == VrmLib.ExpressionPreset.Oh)); } /// /// SetValue /// /// /// public void SetValue(ExpressionKey key, float value) { if (expressionKeyWeights.ContainsKey(key)) { expressionKeyWeights[key] = value; } } /// /// Get a expression value /// /// /// public float GetValue(ExpressionKey key) { if (expressionKeyWeights.ContainsKey(key)) { return expressionKeyWeights[key]; } else { return 0.0f; } } public IEnumerable> GetValues() { return expressionKeyWeights.Select(x => new KeyValuePair(x.Key, x.Value)); } /// /// Set expression values. /// /// public void SetValues(IEnumerable> values) { foreach (var keyValue in values) { if (expressionKeyWeights.ContainsKey(keyValue.Key)) { expressionKeyWeights[keyValue.Key] = keyValue.Value; } } } #region Setter and Getter public float GetPresetValue(VrmLib.ExpressionPreset key) { var expressionKey = new ExpressionKey(key); if (this.expressionKeyWeights.ContainsKey(expressionKey)) { return this.expressionKeyWeights[expressionKey]; } else { return 0.0f; } } public float GetCustomValue(String key) { var expressionKey = ExpressionKey.CreateCustom(key); if (this.expressionKeyWeights.ContainsKey(expressionKey)) { return this.expressionKeyWeights[expressionKey]; } else { return 0.0f; } } public void SetPresetValue(VrmLib.ExpressionPreset key, float value) { var expressionKey = new ExpressionKey(key); if (this.expressionKeyWeights.ContainsKey(expressionKey)) { this.expressionKeyWeights[expressionKey] = value; } } /// key public void SetCustomValue(String key, float value) { var expressionKey = ExpressionKey.CreateCustom(key); if (this.expressionKeyWeights.ContainsKey(expressionKey)) { this.expressionKeyWeights[expressionKey] = value; } } #endregion public IEnumerable GetKeys() { return expressionKeyWeights.Keys; } private (bool ignoreBlink, bool ignoreLookAt, bool ignoreMouth) GetValidateState() { var ignoreBlink = false; var ignoreLookAt = false; var ignoreMouth = false; foreach (var keyWeight in expressionKeyWeights) { if (keyWeight.Value <= 0.0f) continue; // Blink if (!ignoreBlink && m_merger.GetClip(keyWeight.Key).IgnoreBlink && !m_blinkExpressionKeys.Contains(keyWeight.Key)) { ignoreBlink = true; } // LookAt if (!ignoreLookAt && m_merger.GetClip(keyWeight.Key).IgnoreLookAt && !m_lookAtExpressionKeys.Contains(keyWeight.Key)) { ignoreLookAt = true; } // Mouth if (!ignoreMouth && m_merger.GetClip(keyWeight.Key).IgnoreMouth && !m_mouthExpressionKeys.Contains(keyWeight.Key)) { ignoreMouth = true; } } return (ignoreBlink, ignoreLookAt, ignoreMouth); } public (bool ignoreBlink, bool ignoreLookAt, bool ignoreMouth) Begin() { // // get ingore settings // var validateState = GetValidateState(); m_ignoreBlink = validateState.ignoreBlink; m_ignoreLookAt = validateState.ignoreLookAt; m_ignoreMouth = validateState.ignoreMouth; if (validateState.ignoreBlink) { // cancel blink m_blinkExpressionKeys.ForEach(x => expressionKeyWeights[x] = 0.0f); } return validateState; } public void End((bool ignoreBlink, bool ignoreLookAt, bool ignoreMouth) validateState) { if (validateState.ignoreMouth) { m_mouthExpressionKeys.ForEach(x => expressionKeyWeights[x] = 0.0f); } m_merger.SetValues(expressionKeyWeights.Select(x => new KeyValuePair(x.Key, x.Value))); m_merger.Apply(); } } }