// -------------------------------------------------------------------- private void AutodetectWithRules() // TODO - Move this to an autodetection thing { FaceSyncData syncData = target as FaceSyncData; if (syncData.ReferenceText == null || syncData.ReferenceText.Length == 0) { return; } Dictionary <string, FaceSyncBlendSet> rules = FaceSyncSettings.GetSettings().GetHashedRules(); float totalDuration = syncData.GetDuration(); string lowerCaseText = syncData.ReferenceText.ToLower(); for (int i = 0; i < syncData.ReferenceText.Length; ++i) { foreach (var rule in rules) { if (lowerCaseText.Substring(i).StartsWith(rule.Key.ToLower())) { FaceSyncKeyframe kf = new FaceSyncKeyframe(((float)i / syncData.ReferenceText.Length) * totalDuration); kf.BlendSet = rule.Value; syncData.Keyframes.Add(kf); } } } }
// -------------------------------------------------------------------- private DataEntry GetEntry(FaceSyncData data) { DataEntry entry = mDataPool.Count > 0 ? mDataPool.Pop() : new DataEntry(); entry.Time = 0f; entry.Data = data; entry.Duration = data.GetDuration(); return(entry); }
// -------------------------------------------------------------------- public void ApplyBlendData(FaceSyncData data, float time) { for (int i = 0; i < data.Keyframes.Count; ++i) { FaceSyncKeyframe keyframe = data.Keyframes[i]; float keyframeDuration = keyframe.BlendSet.Duration; if (time > keyframe.Time && time < (keyframe.Time + keyframeDuration)) { float keyframeProgress = (time - keyframe.Time) / keyframeDuration; ApplyBlendSet(keyframe.BlendSet, keyframeProgress); } } }
// -------------------------------------------------------------------- public void PlayData(FaceSyncData data) { CacheComponents(); DataEntry entry = GetEntry(data); mDataToApply.Add(entry); if (data.Sound) { mSource.PlayOneShot(data.Sound); } }
// -------------------------------------------------------------------- private void ShowKeyframesUI() { FaceSyncData syncData = target as FaceSyncData; EditorGUI.BeginChangeCheck(); syncData.ReferenceText = EditorGUILayout.TextArea(syncData.ReferenceText); if (EditorGUI.EndChangeCheck()) { EditorUtility.SetDirty(target); } EditorGUILayout.BeginHorizontal(); if (GUILayout.Button("Detect Keyframes")) { AutodetectWithRules(); } if (GUILayout.Button("Clear Keyframes")) { syncData.Keyframes.Clear(); mSelectedKeyframe = -1; } EditorGUILayout.EndHorizontal(); float totalDuration = syncData.GetDuration(); for (int i = 0; i < syncData.Keyframes.Count; ++i) { FaceSyncKeyframe keyframe = syncData.Keyframes[i]; float x = (mWidth - (sBorder * 2)) * (keyframe.Time / totalDuration); string label = keyframe.BlendSet ? keyframe.BlendSet.Label : "!"; GUI.contentColor = keyframe.BlendSet ? Color.white : Color.red; GUI.backgroundColor = i == mSelectedKeyframe ? Color.cyan : (keyframe.BlendSet ? keyframe.BlendSet.Color : Color.white); if (GUI.Button(new Rect(sBorder + x - 10, sInitY - 20, 20, 18), label)) { mSelectedKeyframe = i; } GUI.Box(new Rect(sBorder + x, sInitY, 1, 5), ""); } GUI.contentColor = Color.white; GUI.backgroundColor = Color.white; }
// -------------------------------------------------------------------- private void ShowSoundUI(Rect barRect) { FaceSyncData syncData = target as FaceSyncData; EditorGUILayout.BeginHorizontal(); syncData.Sound = EditorGUILayout.ObjectField(syncData.Sound, typeof(AudioClip), false, null) as AudioClip; if (syncData.Sound != null) { float clipDuration = syncData.Sound.length; float clipPreviewT = Time.realtimeSinceStartup - mClipStartTime; if (clipPreviewT >= clipDuration) { if (GUILayout.Button("Play")) { PlayClip(syncData.Sound); mClipStartTime = Time.realtimeSinceStartup; } } else { GUILayout.Label(clipPreviewT + "s"); } EditorGUILayout.EndHorizontal(); if (clipPreviewT < clipDuration) { Rect clipT = new Rect(barRect); clipT.x = clipT.x + (clipPreviewT / clipDuration) * clipT.width; clipT.y -= 2f; clipT.width = 1f; clipT.height = 10f; GUI.Box(clipT, ""); EditorUtility.SetDirty(target); } } else { EditorGUILayout.EndHorizontal(); } }
// -------------------------------------------------------------------- public override void OnInspectorGUI() { serializedObject.Update(); FaceSyncData syncData = target as FaceSyncData; mWidth = EditorGUIUtility.currentViewWidth; Rect barRect = new Rect(sBorder, sInitY, mWidth - (sBorder * 2f), 5f); EditorGUILayout.Separator(); ShowSoundUI(barRect); if (syncData.Sound != null) { EditorGUILayout.Separator(); ShowKeyframesUI(); float clipDuration = syncData && syncData.Sound ? syncData.Sound.length : 1f; if (syncData.Sound != null) { if (GUI.Button(barRect, "")) { float t = ((Event.current.mousePosition.x - barRect.x) / barRect.width) * clipDuration; syncData.Keyframes.Add(new FaceSyncKeyframe(t)); mSelectedKeyframe = syncData.Keyframes.Count - 1; EditorUtility.SetDirty(target); } float totalDuration = syncData.GetDuration(); if (totalDuration > 0) { float audioPercentage = syncData.Sound.length / totalDuration; GUI.backgroundColor = Color.cyan; GUI.Box(new Rect(sBorder, sInitY, (mWidth - (sBorder * 2)) * audioPercentage, 5), ""); GUI.backgroundColor = Color.white; } } if (mSelectedKeyframe >= 0) { GUILayout.BeginArea(new Rect(sBorder, sInitY + 30, mWidth - (sBorder * 2), 200)); ShowKeyframeDataUI(syncData.Keyframes[mSelectedKeyframe], clipDuration); GUILayout.EndArea(); } else { GUILayout.BeginArea(new Rect(sBorder, sInitY + 30, mWidth - (sBorder * 2), 200)); GUILayout.Label("Select a keyframe or click on the timeline to create a new keyframe."); GUILayout.EndArea(); } } serializedObject.ApplyModifiedProperties(); }