using System; using System.Collections.Generic; using Convai.Scripts.Runtime.Core; using Convai.Scripts.Runtime.Extensions; using Convai.Scripts.Runtime.Features.LipSync.Models; using Convai.Scripts.Runtime.Features.LipSync.Types; using Service; using UnityEngine; namespace Convai.Scripts.Runtime.Features.LipSync { public class ConvaiLipSync : MonoBehaviour { [HideInInspector] public FaceModel faceModel = FaceModel.OvrModelName; [field: SerializeField] [field: Tooltip("Assign the skin renderers and its respective effectors, along with the bones used for Facial Expression")] public FacialExpressionData FacialExpressionData { get; private set; } = new(); [field: SerializeField] [field: Range(0f, 1f)] [field: Tooltip("This decides how much blending will occur between two different blendshape frames")] public float WeightBlendingPower { get; private set; } = 0.5f; [SerializeField] private List characterEmotions; private ConvaiNPC _convaiNPC; public ConvaiLipSyncApplicationBase ConvaiLipSyncApplicationBase { get; private set; } /// /// This function will automatically set any of the unassigned skinned mesh renderers to appropriate values using regex /// based functions. /// Sets the references of the required variables /// Sets wait for lipsync to true /// private void Start() { FindSkinMeshRenderer(); _convaiNPC = GetComponent(); ConvaiLipSyncApplicationBase = gameObject.GetOrAddComponent(); ConvaiLipSyncApplicationBase.Initialize(this, _convaiNPC); SetCharacterLipSyncing(true); } private void OnDisable() { StopLipSync(); } private void OnApplicationQuit() { StopLipSync(); } public event Action OnCharacterLipSyncing; private void FindSkinMeshRenderer() { if (FacialExpressionData.Head.Renderer == null) FacialExpressionData.Head.Renderer = transform.GetComponentOnChildWithMatchingRegex("(.*_Head|CC_Base_Body)"); if (FacialExpressionData.Teeth.Renderer == null) FacialExpressionData.Teeth.Renderer = transform.GetComponentOnChildWithMatchingRegex("(.*_Teeth|CC_Base_Teeth)"); if (FacialExpressionData.Tongue.Renderer == null) FacialExpressionData.Tongue.Renderer = transform.GetComponentOnChildWithMatchingRegex("(.*_Tongue|CC_Base_Tongue)"); } /// /// Overrides the character emotions list /// /// list of new emotions public void SetCharacterEmotions(List newEmotions) { characterEmotions = new List(newEmotions); } /// /// Returns Direct reference of the character emotions [Not Recommended to directly change this list] /// /// public List GetCharacterEmotions() { return characterEmotions; } /// /// Fires an event with update the Character Lip Syncing State /// /// private void SetCharacterLipSyncing(bool value) { OnCharacterLipSyncing?.Invoke(value); } /// /// Purges the latest chuck of lipsync frames /// public void PurgeExcessFrames() { ConvaiLipSyncApplicationBase?.PurgeExcessBlendShapeFrames(); } /// /// Stops the Lipsync by clearing the frames queue /// public void StopLipSync() { ConvaiLipSyncApplicationBase?.ClearQueue(); } } }