private void OnGUI() { EditorGUILayout.HelpBox("This utility lets you improve runtime performance by pre-processing the animation for a LipSyncData clip and a specific LipSync character, and storing it in the clip.\nThis can help remove any pauses or frame drops when starting to play a LipSyncData clip, but will tie the clip to a specific character. Attempting to play a pre-processed clip on a different character may not work correctly.", MessageType.None); EditorGUILayout.Space(); character = (LipSync)EditorGUILayout.ObjectField("LipSync Character", character, typeof(LipSync), true); EditorGUILayout.Space(); GUILayout.Label("LipSyncData Clips"); GUILayout.Space(2); for (int i = 0; i < dataFiles.Count; i++) { GUILayout.BeginHorizontal(); dataFiles[i] = (LipSyncData)EditorGUILayout.ObjectField(dataFiles[i], typeof(LipSyncData), true); if (GUILayout.Button("Remove", GUILayout.Width(100))) { dataFiles.RemoveAt(i); return; } GUILayout.EndHorizontal(); } GUILayout.Space(2); EditorGUILayout.BeginHorizontal(); if (GUILayout.Button("Add Empty Slot")) { dataFiles.Add(null); } if (GUILayout.Button("Add Selected Clip(s)")) { var select = Selection.GetFiltered <LipSyncData>(SelectionMode.Assets); for (int i = 0; i < select.Length; i++) { if (!dataFiles.Contains(select[i])) { dataFiles.Add(select[i]); } } } EditorGUILayout.EndHorizontal(); if (GUILayout.Button("Add All Clips In Project")) { dataFiles.Clear(); var all = AssetDatabase.FindAssets("t:LipSyncData"); Resources.FindObjectsOfTypeAll <LipSyncData>(); for (int i = 0; i < all.Length; i++) { dataFiles.Add(AssetDatabase.LoadAssetAtPath <LipSyncData>(AssetDatabase.GUIDToAssetPath(all[i]))); } } EditorGUILayout.Space(); EditorGUI.BeginDisabledGroup(!character || dataFiles.Count == 0); if (GUILayout.Button("Process Data")) { bool overwrite = false; int actualCount = 0; for (int i = 0; i < dataFiles.Count; i++) { var path = AssetDatabase.GetAssetPath(dataFiles[i]); if (string.IsNullOrEmpty(path)) { continue; } if (dataFiles[i].isPreprocessed && !overwrite) { var answer = EditorUtility.DisplayDialogComplex("Overwrite Data?", "The clip '" + dataFiles[i].name + "' already has pre-processed data. Are you sure you want to continue and overwrite this data?", "Yes", "No", "Yes To All"); if (answer == 1) { continue; } else if (answer == 2) { overwrite = true; } } EditorUtility.DisplayProgressBar("Processing Data", "Processing Clip " + i + " of " + dataFiles.Count, dataFiles.Count / (float)i); character.TempLoad(dataFiles[i].phonemeData, dataFiles[i].emotionData, dataFiles[i].clip, dataFiles[i].length); character.ProcessData(); dataFiles[i].isPreprocessed = true; character.GetCurveDataOut(out dataFiles[i].indexBlendables, out dataFiles[i].animCurves, out dataFiles[i].bones, out dataFiles[i].boneCurves, out dataFiles[i].boneNeutralPositions, out dataFiles[i].boneNeutralRotations, out dataFiles[i].boneNeutralScales); dataFiles[i].targetComponentID = character.GetInstanceID(); LipSyncData outputFile = AssetDatabase.LoadAssetAtPath <LipSyncData>(path); if (outputFile != null) { EditorUtility.CopySerialized(dataFiles[i], outputFile); } else { outputFile = CreateInstance <LipSyncData>(); EditorUtility.CopySerialized(dataFiles[i], outputFile); AssetDatabase.CreateAsset(outputFile, path); } actualCount++; } EditorUtility.ClearProgressBar(); EditorUtility.DisplayDialog("Processing Complete", "Finished processing " + actualCount + " clip(s).", "Ok"); AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); Close(); } EditorGUI.EndDisabledGroup(); }