Files
HauntedBloodlines/Assets/PuppetFace/Scripts/Editor/PuppetFaceEditor.cs
2025-05-29 22:31:40 +03:00

1729 lines
56 KiB
C#

using UnityEditor;
using UnityEngine;
using System.Collections.Generic;
using UnityEditor.Compilation;
using System;
using System.Linq;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
//using SFB;
namespace PuppetFace
{
public class PuppetFaceEditor : EditorWindow
{
public Vector2 scrollPosition = Vector2.zero;
public static List<string> blendShapeTextures;
public static SkinnedMeshRenderer CurrentSkinnedModel;
public static GameObject CurrentBlendShapeModel;
public static int CurrentBlendShapeIndex = -1;
public static int CurrentSelectedPhonemeMarker = -1;
public static float TimeVal = 0;
public static bool Playing = false;
public static float ShortStop = -1f;
public static int WaveFormWidth = 1500;
public static int WaveFormPosX = 0;
public static int WaveFormPosY = 0;
public static int WaveFormOffsetX = 0;
private List<PhonemeMarker> _phonemeMarkers;
private GUIStyle _phonemeMarkerStyle;
private GUIStyle _defaultStyle;
private static PuppetFaceEditor _puppetFaceEditor;
private static AudioSource AudioSourceLoaded;
public static AudioClip AudioClipLoaded;
private static LipSync LipSyncLoaded;
private static LipSync[] LipSyncInScene;
private static string[] LipSyncInSceneString;
private static int LipSyncSelected;
private static string[] AudioClipNames;
float editorDeltaTime = 0f;
float lastTimeSinceStartup = 0f;
private string[] options;
private static List<int> selectedOptions;
private static int flags = -1;
private static int BlendShapeType = 1;
private static int BonePoseIndex = -1;
public static int AudioClipsToConvert = 0;
public static List<string> filesToConvert = new List<string>();
public static string[] waveNames = new string[0];
private static string _puppetFacePath;
[MenuItem("Window/Puppet Face/Lip Sync Editor")]
public static void ShowWindow()
{
_puppetFaceEditor = (PuppetFaceEditor)EditorWindow.GetWindow(typeof(PuppetFaceEditor));
_puppetFaceEditor.titleContent = new GUIContent();
_puppetFaceEditor.titleContent.text = "Lip Sync Editor";
_puppetFaceEditor.position = new Rect(100, 200, 1000, 600);
_puppetFaceEditor.name = "Lip Sync Editor";
blendShapeTextures = new List<string>();
GetEditorData();
if (blendShapeTextures.Count == 0)
{
for (int i = 0; i < 10; i++)
{
string faceShape = (_puppetFacePath +"/Textures/GUI/img/lisa" + i + ".png");
if (!blendShapeTextures.Contains(faceShape))
blendShapeTextures.Add(faceShape);
}
SetEditorData();
}
_puppetFaceEditor.Show();
}
[MenuItem("Window/Puppet Face/Component/Lip Sync")]
public static void AddLipSync()
{
Selection.activeGameObject.AddComponent<LipSync>();
}
[MenuItem("Window/Puppet Face/Component/Blend Shape Manager")]
public static void AddBlendShapeManager()
{
Selection.activeGameObject.AddComponent<BlendShapeManager>();
}
[MenuItem("Window/Puppet Face/Component/Performance Capture")]
public static void AddPerformanceCapture()
{
Selection.activeGameObject.AddComponent<PerformanceCapture>();
}
[MenuItem("Window/Puppet Face/Component/Eye Motion")]
public static void AddEyeMotion()
{
Selection.activeGameObject.AddComponent<EyeMotion>();
}
private void OnEnable()
{
_puppetFacePath = "Assets" + RecursivelyFindFolderPath().Substring(Application.dataPath.Length);
_phonemeMarkerStyle = new GUIStyle();
_defaultStyle = new GUIStyle();
string phonemeMarkerPath = _puppetFacePath + "/Textures/GUI/phonemeMarker.png";
_phonemeMarkerStyle.normal.background = EditorGUIUtility.Load(phonemeMarkerPath) as Texture2D;
_phonemeMarkerStyle.normal.textColor = Color.white;
_defaultStyle.normal.textColor = Color.white;
_phonemeMarkerStyle.border = new RectOffset(12, 12, 12, 12);
CheckForLipSyncs();
}
private static void CheckForLipSyncs()
{
LipSyncInScene = FindObjectsOfType<LipSync>();
LipSyncInSceneString = new string[LipSyncInScene.Length];
for (int i = 0; i < LipSyncInScene.Length; i++)
{
LipSyncInSceneString[i] = LipSyncInScene[i].gameObject.name;
}
}
void OnGUI()
{
if (_puppetFaceEditor == null)
{
_puppetFaceEditor = (PuppetFaceEditor)EditorWindow.GetWindow(typeof(PuppetFaceEditor));
_puppetFaceEditor.name = "Lip Sync Editor";
RefreshNodes(Vector2.zero);
}
int widthPad = 0;
int heightPad = 20;
Color defaultColor = GUI.backgroundColor;
string BGPath = _puppetFacePath + "/Textures/GUI/BG.png";
string BGDarkPath = _puppetFacePath + "/Textures/GUI/BGDark.png";
Texture BGAsset = AssetDatabase.LoadAssetAtPath(BGPath, typeof(Texture)) as Texture;
Texture BGDarkAsset = AssetDatabase.LoadAssetAtPath(BGDarkPath, typeof(Texture)) as Texture;
GUI.DrawTexture(new Rect(0, 0, 9999, 9999), BGAsset, ScaleMode.StretchToFill);
GUI.backgroundColor = defaultColor;
GetEditorData();
GUILayout.BeginArea(new Rect(10, 10, Screen.width - 20, Screen.height - 50), EditorStyles.helpBox);
GUILayout.EndArea();
GUILayout.BeginArea(new Rect(10, 10, Screen.width - 20, 70), EditorStyles.helpBox);
GUILayout.Space(25);
GUILayout.BeginHorizontal();
GUILayout.FlexibleSpace();
bool notYetLoaded = false;
if (!notYetLoaded)
{
CheckForLipSyncs();
if (LipSyncInScene.Length > 0)
{
LipSyncSelected = Mathf.Clamp(LipSyncSelected, 0, LipSyncInScene.Length - 1);
notYetLoaded = CheckForSelectedLipSync(LipSyncInScene[LipSyncSelected].gameObject, notYetLoaded);
}
}
//Debug.Log(waveNames.Length);
if (waveNames.Length == 0)
{
SetAudioClipData();
}
/*EditorGUI.BeginChangeCheck();
AudioClipsToConvert = EditorGUILayout.MaskField(AudioClipsToConvert, waveNames);
if (EditorGUI.EndChangeCheck())
{
SetAudioClipData();
}*/
if (GUILayout.Button("Convert Audio (File)"))
{
ConvertAudioToLipSyncFile();
}
if (GUILayout.Button("Convert Audio (Folder)"))
{
ConvertAudioToLipSyncFolder();
}
if (GUILayout.Button("Reload"))
{
LipSyncLoaded.Initialized = false;
ReloadNodes(Vector2.zero);
}
if (GUILayout.Button("Save"))
{
SavePhonemes();
}
GUILayout.FlexibleSpace();
GUILayout.EndHorizontal();
GUILayout.EndArea();
GUILayout.BeginArea(new Rect(11, 0, Screen.width - 22, Screen.height - 20));
if (_phonemeMarkers == null)
{
_phonemeMarkers = new List<PhonemeMarker>();
}
if (Selection.activeGameObject)
{
MeshRenderer mr = Selection.activeGameObject.GetComponent<MeshRenderer>();
MeshModifier mm = Selection.activeGameObject.GetComponent<MeshModifier>();
SkinnedMeshRenderer smr = Selection.activeGameObject.GetComponent<SkinnedMeshRenderer>();
if (mm == null)
CurrentSkinnedModel = smr;
if (Selection.activeGameObject.GetComponent<AudioSource>() && Selection.activeGameObject.GetComponent<LipSync>())
{
notYetLoaded = CheckForSelectedLipSync(Selection.activeGameObject, notYetLoaded);
}
else if (mr != null && mm == null)
{
AudioSourceLoaded = null;
LipSyncLoaded = null;
}
}
if (LipSyncLoaded != null)
{
if (AudioSourceLoaded != null && AudioClipLoaded != null && AudioClipNames != null && AudioClipNames.Length > 0)
{
heightPad += 50;
GUI.DrawTexture(new Rect(widthPad, heightPad, Screen.width - 10, 160), BGDarkAsset, ScaleMode.StretchToFill);
}
GUILayout.BeginArea(new Rect(0, 10, Screen.width - 20, 20), EditorStyles.helpBox);
GUILayout.BeginHorizontal();
if (LipSyncInScene.Length > 0)
{
EditorGUI.BeginChangeCheck();
LipSyncSelected = EditorGUILayout.Popup(LipSyncSelected, LipSyncInSceneString);
if (EditorGUI.EndChangeCheck())
{
CheckForLipSyncs();
if (LipSyncInScene.Length > 0)
{
LipSyncSelected = Mathf.Clamp(LipSyncSelected, 0, LipSyncInScene.Length - 1);
Selection.activeGameObject = LipSyncInScene[LipSyncSelected].gameObject;
notYetLoaded = CheckForSelectedLipSync(LipSyncInScene[LipSyncSelected].gameObject, notYetLoaded);
LipSyncLoaded = LipSyncInScene[LipSyncSelected];
}
}
}
if (LipSyncLoaded.LipSyncFiles != null && LipSyncLoaded.LipSyncFiles.Length > 0)
{
EditorGUI.BeginChangeCheck();
LipSyncLoaded.LipSyncIndex = EditorGUILayout.Popup(LipSyncLoaded.LipSyncIndex, AudioClipNames);
if (EditorGUI.EndChangeCheck())
{
LipSyncLoaded.SetIndex(LipSyncLoaded.LipSyncIndex);
AudioClipLoaded = LipSyncLoaded.AudioClips[LipSyncLoaded.LipSyncIndex];
AudioSourceLoaded.clip = AudioClipLoaded;
ReloadNodes(Vector2.zero);
DrawNodes();
}
if(LipSyncLoaded.NewAudioAdded)
{
ReloadNodes(Vector2.zero);
LipSyncLoaded.NewAudioAdded = false;
}
}
GUILayout.FlexibleSpace();
GUILayout.EndHorizontal();
GUILayout.EndArea();
if (AudioSourceLoaded != null && AudioClipLoaded != null && AudioClipNames != null && AudioClipNames.Length > 0)
{
if (AudioSourceLoaded != null && AudioClipLoaded != null && AudioClipNames != null && AudioClipNames.Length > 0)
{
EditorGUI.BeginChangeCheck();
TimeVal = GUI.HorizontalSlider(new Rect(new Vector2(WaveFormPosX, heightPad + 20), new Vector2(WaveFormWidth, 100)), TimeVal, 0, AudioClipLoaded.length);
if (EditorGUI.EndChangeCheck())
{
if (!Application.isPlaying)
{
if (AudioSourceLoaded.clip.length > TimeVal)
{
SetLipSync();
AudioSourceLoaded.time = TimeVal;
ShortStop = .2f;
AudioSourceLoaded.Play();
}
}
}
}
WaveFormPosY = heightPad;
Texture PlayButtonAsset = AssetDatabase.LoadAssetAtPath(_puppetFacePath +"/Textures/GUI/PlayButton.png", typeof(Texture)) as Texture;
Texture PlayButtonOnAsset = AssetDatabase.LoadAssetAtPath(_puppetFacePath +"/Textures/GUI/PlayButtonOn.png", typeof(Texture)) as Texture;
Texture StopButtonAsset = AssetDatabase.LoadAssetAtPath(_puppetFacePath +"/Textures/GUI/StopButton.png", typeof(Texture)) as Texture;
Texture StopButtonOnAsset = AssetDatabase.LoadAssetAtPath(_puppetFacePath +"/Textures/GUI/StopButtonOn.png", typeof(Texture)) as Texture;
GUIStyle buttonStyle = new GUIStyle();
buttonStyle.stretchWidth = true;
buttonStyle.stretchHeight = true;
if (GUI.Button(new Rect(widthPad + 30, heightPad - 35, 32, 32), Playing ? PlayButtonOnAsset : PlayButtonAsset, buttonStyle))
{
if (!Playing && !Application.isPlaying)
{
//PlayClip(clip);
AudioSourceLoaded.time = TimeVal;
AudioSourceLoaded.Play();
Playing = true;
}
}
if (GUI.Button(new Rect(widthPad + 62, heightPad - 35, 32, 32), Playing ? StopButtonAsset : StopButtonOnAsset, buttonStyle))
{
if (!Application.isPlaying)
{
AudioSourceLoaded.Stop();
ShortStop = -1f;
Playing = false;
}
}
GUIStyle textFieldStyle = new GUIStyle();
textFieldStyle.normal.textColor = Color.white;
textFieldStyle.normal.background = BGDarkAsset as Texture2D;
textFieldStyle.contentOffset = new Vector2(10, 10);
TimeVal = float.Parse(GUI.TextField(new Rect(widthPad + 94, heightPad - 35, 100, 32), TimeVal.ToString(), textFieldStyle));
PaintWaveformSpectrum(AudioClipLoaded, 1, new Rect(WaveFormPosX, WaveFormPosY, WaveFormWidth, 100), new Color(14f / 255f, 229f / 255f, 198f / 255f, 1f));
heightPad += 20;
if (notYetLoaded)
{
ReloadNodes(Vector2.zero);
}
DrawNodes();
if (LipSyncLoaded.Skin == null)
{
LipSyncLoaded.Skin = LipSyncLoaded.GetComponent<SkinnedMeshRenderer>();
return;
}
string[] BlendShapeNames = GetArrayBlendShapes(LipSyncLoaded.Skin);
for (int i = 0; i < 9; i++)
{
CreateLipSyncBlendShapeButton(i, widthPad + (i * 110), heightPad, BlendShapeNames);
}
heightPad += 150;
if (LipSyncLoaded!=null && LipSyncLoaded.Skin != null && LipSyncLoaded.Skin.sharedMesh != null)
{
if (options == null || options.Length!= LipSyncLoaded.Skin.sharedMesh.subMeshCount)
{
options = new string[LipSyncLoaded.Skin.sharedMesh.subMeshCount];
for (int i = 0; i < options.Length; i++)
{
if (i < LipSyncLoaded.Skin.sharedMaterials.Length)
options[i] = LipSyncLoaded.Skin.sharedMaterials[i].name;
else
options[i] = ("Mesh_" + i);
}
flags = -1;
}
EditorGUI.LabelField(new Rect(widthPad + 15, heightPad + 185, 100, 16), "Sub Mesh");
EditorGUI.BeginChangeCheck();
flags = EditorGUI.MaskField(new Rect(widthPad + 94, heightPad + 185, 100, 16), flags, options);
if(EditorGUI.EndChangeCheck())
{
options = new string[LipSyncLoaded.Skin.sharedMesh.subMeshCount];
for (int i = 0; i < options.Length; i++)
{
if (i < LipSyncLoaded.Skin.sharedMaterials.Length)
options[i] = LipSyncLoaded.Skin.sharedMaterials[i].name;
else
options[i] = ("Mesh_" + i);
}
}
selectedOptions = new List<int>();
for (int i = 0; i < options.Length; i++)
{
if ((flags & (1 << i)) == (1 << i)) selectedOptions.Add(i);
}
EditorGUI.LabelField(new Rect(widthPad + 225, heightPad + 185, 100, 16), "Type");
string[] blendshapeTypes = { "From Bind Pose", "From Bind Pose (Skinned)", "From Current Pose" };
BlendShapeType = EditorGUI.Popup(new Rect(widthPad + 284, heightPad + 185, 100, 16),BlendShapeType, blendshapeTypes);
}
}
ProcessNodeEvents(Event.current);
ProcessEvents(Event.current);
if (GUI.changed)
{
if (LipSyncLoaded != null)
{
LipSyncLoaded.InitializeFromData(MakeFaceShapeData(_phonemeMarkers), LipSyncLoaded.LipSyncIndex);
}
Repaint();
}
string LogoPath = _puppetFacePath +"/Textures/GUI/PuppetFaceLogo.png";
Texture LogoAsset = AssetDatabase.LoadAssetAtPath(LogoPath, typeof(Texture)) as Texture;
GUI.DrawTexture(new Rect(_puppetFaceEditor.position.width - 84, 0, 64, 64), LogoAsset, ScaleMode.ScaleToFit);
}
GUILayout.EndArea();
}
private static void SetAudioClipData()
{
DirectoryInfo directoryInfo = new DirectoryInfo(Application.dataPath);
FileInfo[] fileInfo = directoryInfo.GetFiles("*.wav", SearchOption.AllDirectories);
waveNames = new string[fileInfo.Length];
//List<DirectoryInfo> uniqueDirs = new List<DirectoryInfo>();
for (int i = 0; i < waveNames.Length; i++)
{
waveNames[i] = fileInfo[i].Name;// (fileInfo[i].Directory.Name + "/" + fileInfo[i].Name);
/*if(!uniqueDirs.Contains(fileInfo[i].Directory))
{
uniqueDirs.Add(fileInfo[i].Directory);
}*/
}
filesToConvert.Clear();
for (int i = 0; i < waveNames.Length; i++)
{
if ((AudioClipsToConvert & (1 << i)) == (1 << i)) filesToConvert.Add(fileInfo[i].FullName);
}
}
private static bool CheckForSelectedLipSync(GameObject lipSyncGO, bool notYetLoaded)
{
if (AudioSourceLoaded == null)
{
notYetLoaded = true;
}
LipSyncLoaded = lipSyncGO.GetComponent<LipSync>();
LipSyncInScene = FindObjectsOfType<LipSync>();
LipSyncInSceneString = new string[LipSyncInScene.Length];
for (int i = 0; i < LipSyncInScene.Length; i++)
{
LipSyncInSceneString[i] = LipSyncInScene[i].gameObject.name;
if (LipSyncLoaded == LipSyncInScene[i])
LipSyncSelected = i;
}
AudioSourceLoaded = lipSyncGO.GetComponent<AudioSource>();
if (LipSyncLoaded.AudioClips != null && LipSyncLoaded.AudioClips.Length > 0 && LipSyncLoaded.LipSyncIndex < LipSyncLoaded.LipSyncFiles.Length)
{
LipSyncLoaded.LipSyncIndex = Mathf.Clamp(LipSyncLoaded.LipSyncIndex, 0, LipSyncLoaded.LipSyncFiles.Length - 1);
AudioClipLoaded = LipSyncLoaded.AudioClips[LipSyncLoaded.LipSyncIndex];
AudioSourceLoaded.clip = AudioClipLoaded;
AudioClipNames = new string[LipSyncLoaded.LipSyncFiles.Length];
for (int i = 0; i < LipSyncLoaded.LipSyncFiles.Length; i++)
{
if (LipSyncLoaded.LipSyncFiles[i] != null)
AudioClipNames[i] = LipSyncLoaded.LipSyncFiles[i].name;
}
}
else
{
AudioClipLoaded = null;
}
return notYetLoaded;
}
public string[] GetArrayBlendShapes(SkinnedMeshRenderer skin)
{
Mesh m = skin.sharedMesh;
string[] arr;
arr = new string[m.blendShapeCount + 1];
for (int i = 0; i < m.blendShapeCount; i++)
{
arr[i] = m.GetBlendShapeName(i);
}
arr[m.blendShapeCount] = "Not Set";
return arr;
}
private void ConvertAudioToLipSyncFile()
{
DirectoryInfo directoryInfo = new DirectoryInfo(Application.dataPath);
FileInfo[] fileInfo = directoryInfo.GetFiles("*.wav", SearchOption.AllDirectories);
string startDir = "";
if (fileInfo.Length > 0)
startDir = fileInfo[0].Directory.FullName;
string path = EditorUtility.OpenFilePanel("Select Wav Files", startDir, "wav");
if (path == "")
return;
string[] paths = new string[1] { path };
ConvertAudioToLipSyncAll(paths);
}
private void ConvertAudioToLipSyncFolder()
{
DirectoryInfo directoryInfo = new DirectoryInfo(Application.dataPath);
FileInfo[] fileInfo = directoryInfo.GetFiles("*.wav", SearchOption.AllDirectories);
string startDir = "";
if (fileInfo.Length > 0)
startDir = fileInfo[0].Directory.FullName;
string path = EditorUtility.OpenFolderPanel("Select Wav Files", startDir, "");
if (path == "")
return;
string[] files = Directory.GetFiles(path);
List<string> wavFiles = new List<string>();
foreach (string file in files)
if (file.EndsWith(".wav"))
wavFiles.Add(file);
ConvertAudioToLipSyncAll(wavFiles.ToArray());
}
private void ConvertAudioToLipSyncAll(string[] files)
{
/*var extensions = new[] {
new ExtensionFilter("Sound Files", "mp3", "wav" ),};
string[] files = StandaloneFileBrowser.OpenFilePanel("Select Wav Files", "", extensions, true);
*/
if (files.Length != 0)
{
foreach (string path in files)
{
string relativepath = path;
relativepath = "Assets" + path.Substring(Application.dataPath.Length);
relativepath = "Assets" + path.Substring(Application.dataPath.Length);
//Debug.Log(relativepath + " " + path);
AudioClip audioCip = AssetDatabase.LoadAssetAtPath(relativepath, typeof(AudioClip)) as AudioClip;
string lipSyncPath = LipSync.ConvertAudioToPhoneme(audioCip);
// get correct lip sync
if (LipSyncLoaded == null)
{
if (Selection.activeGameObject != null)
{
LipSyncLoaded = Selection.activeGameObject.GetComponent<LipSync>();
//LipSync lipSync = Selection.activeGameObject.GetComponent<LipSync>();
//if (lipSync == null)
//{
if (LipSyncLoaded != null)
{
SkinnedMeshRenderer smr = Selection.activeGameObject.GetComponent<SkinnedMeshRenderer>();
if (smr == null)
{
MeshRenderer mr = Selection.activeGameObject.GetComponent<MeshRenderer>();
MeshFilter mf = Selection.activeGameObject.GetComponent<MeshFilter>();
if (mr == null)
{
Debug.LogWarning("Please select a gameObject with a SkinnedMeshRenderer / MeshRenderer & MeshFilter");
return;
}
else
{
Material[] mats = mr.sharedMaterials;
smr = Selection.activeGameObject.AddComponent<SkinnedMeshRenderer>();
smr.sharedMesh = mf.sharedMesh;
smr.sharedMaterials = mats;
DestroyImmediate(mf);
DestroyImmediate(mr);
}
}
LipSyncLoaded.Skin = smr;
}
else
Debug.LogWarning("Please Select A GameObject With A lipSync Component");
//}
}
else
{
LipSync[] lipSyncsInScene = FindObjectsOfType<LipSync>();
if (lipSyncsInScene.Length > 0)
LipSyncLoaded = lipSyncsInScene[0];
else
Debug.LogWarning("Please Select A GameObject With A lipSync Component");
}
}
if (LipSyncLoaded != null)
{
Selection.activeGameObject = LipSyncLoaded.gameObject;
List<AudioClip> audioClips = new List<AudioClip>();
if (LipSyncLoaded.AudioClips != null && LipSyncLoaded.AudioClips.Length > 0)
audioClips = LipSyncLoaded.AudioClips.ToList();
int addedIndex = 0;
if (audioClips.Contains(audioCip))
{
addedIndex = audioClips.IndexOf(audioCip);
}
else
{
audioClips.Add(audioCip);
addedIndex = audioClips.Count - 1;
}
LipSyncLoaded.AudioClips = audioClips.ToArray();
AssetDatabase.Refresh();
List<TextAsset> lipSyncFiles = new List<TextAsset>();
if (LipSyncLoaded.LipSyncFiles != null && LipSyncLoaded.LipSyncFiles.Length > 0)
lipSyncFiles = LipSyncLoaded.LipSyncFiles.ToList();
relativepath = lipSyncPath;
if (lipSyncPath.StartsWith(Application.dataPath))
{
relativepath = "Assets" + lipSyncPath.Substring(Application.dataPath.Length);
}
TextAsset textAsset = AssetDatabase.LoadAssetAtPath(relativepath, typeof(TextAsset)) as TextAsset;
if (addedIndex < lipSyncFiles.Count)
lipSyncFiles[addedIndex] = textAsset;
else
{
lipSyncFiles.Add(textAsset);
addedIndex = LipSyncLoaded.LipSyncFiles.Length - 1;
}
LipSyncLoaded.LipSyncFiles = lipSyncFiles.ToArray();
AudioSourceLoaded = LipSyncLoaded.gameObject.GetComponent<AudioSource>();
LipSyncLoaded.LipSyncIndex = addedIndex;// ;
LipSyncLoaded.Initialized = false;
LipSyncLoaded.InitializeFromData(MakeFaceShapeData(_phonemeMarkers), LipSyncLoaded.LipSyncIndex);
//LipSyncLoaded.InitializeFromFile();
}
}
}
}
public void SavePhonemes()
{
LipSyncLoaded.InitializeFromData(MakeFaceShapeData(_phonemeMarkers), LipSyncLoaded.LipSyncIndex);
if (LipSyncLoaded != null)
{
if (LipSyncLoaded.FaceShapes != null && LipSyncLoaded.FaceShapes.Count > LipSyncLoaded.LipSyncIndex)
{
var serializer = new XmlSerializer(typeof(LipSyncType));
string path = AssetDatabase.GetAssetPath(LipSyncLoaded.LipSyncFiles[LipSyncLoaded.LipSyncIndex]);// "Assets/LipSync/output.xml";
LipSyncLoaded.FaceShapes[LipSyncLoaded.LipSyncIndex].faceShapes.Clear();
List<FaceShape> newFaceShape = new List<FaceShape>();
LipSyncType test = new LipSyncType();
test.mouthCues = new List<mouthCue>();
for (int i = 0; i < _phonemeMarkers.Count; i++)
{
mouthCue cue = new mouthCue();
cue.start = _phonemeMarkers[i].Start;
cue.end = _phonemeMarkers[i].End;
cue.shapeName = _phonemeMarkers[i].Label;
cue.strength = _phonemeMarkers[i].Strength;
cue.blendShapeID = _phonemeMarkers[i].BlendShapeID;
test.mouthCues.Add(cue);
newFaceShape.Add(new FaceShape(_phonemeMarkers[i].Start, _phonemeMarkers[i].End, _phonemeMarkers[i].Label, cue.strength, cue.blendShapeID));
}
LipSyncLoaded.FaceShapes[LipSyncLoaded.LipSyncIndex].faceShapes = newFaceShape;
var stream = new FileStream(path, FileMode.Create);
serializer.Serialize(stream, test);
stream.Close();
Debug.Log(LipSyncLoaded.LipSyncFiles[LipSyncLoaded.LipSyncIndex].name + " Saved.");
//UnityEngine.Debug.Log("Saving path " + path);
}
}
}
static public string GetPrestonBlairNamesFromIndex(int index)
{
switch (index)
{
case 0:
return "MBP";
case 1:
return "etc";
case 2:
return "E";
case 3:
return "AI";
case 4:
return "O";
case 5:
return "U";
case 6:
return "FV";
case 7:
return "L";
case 8:
return "rest";
}
return "";
}
static public string GetPrestonBlairNamesFromLetter(string letter)
{
switch (letter)
{
case "A":
return "MBP";
case "B":
return "etc";
case "C":
return "E";
case "D":
return "AI";
case "E":
return "O";
case "F":
return "U";
case "G":
return "FV";
case "H":
return "L";
case "X":
return "rest";
}
return "";
}
private static void CreateLipSyncBlendShapeButton(int id, int widthPad, int heightPad, string[] BlendShapeNames)
{
string faceShape = (_puppetFacePath +"/Textures/GUI/img/lisa" + id + ".png");
Texture faceShapeTexture = AssetDatabase.LoadAssetAtPath(faceShape, typeof(Texture)) as Texture;
if (CurrentBlendShapeModel != null)
{
if (CurrentBlendShapeIndex != id)
{
GUI.color = new Color(1, 1, 1, .5f);
}
else
{
if (GUI.Button(new Rect(widthPad + 10, heightPad + 230 + faceShapeTexture.height * .25f, faceShapeTexture.width * .25f, 20), "Discard"))
{
LipSyncLoaded.GetComponent<SkinnedMeshRenderer>().enabled = true;
if (CurrentBlendShapeModel != null)
DestroyImmediate(CurrentBlendShapeModel);
Selection.activeGameObject = LipSyncLoaded.GetComponent<SkinnedMeshRenderer>().gameObject;
CurrentBlendShapeModel = null;
if (LipSyncLoaded.TransformStates.Count > 0)
{
for (int j = 0; j < LipSyncLoaded.FaceBones.Length; j++)
{
FaceControl fc = LipSyncLoaded.FaceBones[j].gameObject.GetComponent<FaceControl>();
if (fc != null)
DestroyImmediate(fc);
LipSyncLoaded.FaceBones[j].localPosition = LipSyncLoaded._currentTransforms.transformStates[j].position;
LipSyncLoaded.FaceBones[j].localRotation = LipSyncLoaded._currentTransforms.transformStates[j].rotation;
LipSyncLoaded.FaceBones[j].localScale = LipSyncLoaded._currentTransforms.transformStates[j].scale;
}
}
BonePoseIndex = -1;
}
}
}
else if (BonePoseIndex != -1)
{
if (BonePoseIndex == id)
{
if (GUI.Button(new Rect(widthPad + 10, heightPad + 230 + faceShapeTexture.height * .25f, faceShapeTexture.width * .25f, 20), "Discard"))
{
if (LipSyncLoaded.TransformStates.Count > 0)
{
for (int j = 0; j < LipSyncLoaded.FaceBones.Length; j++)
{
FaceControl fc = LipSyncLoaded.FaceBones[j].gameObject.GetComponent<FaceControl>();
if (fc != null)
DestroyImmediate(fc);
LipSyncLoaded.FaceBones[j].localPosition = LipSyncLoaded._currentTransforms.transformStates[j].position;
LipSyncLoaded.FaceBones[j].localRotation = LipSyncLoaded._currentTransforms.transformStates[j].rotation;
LipSyncLoaded.FaceBones[j].localScale = LipSyncLoaded._currentTransforms.transformStates[j].scale;
}
}
BonePoseIndex = -1;
}
}
}
if (GUI.Button(new Rect(widthPad + 10, heightPad + 190, faceShapeTexture.width * .25f, faceShapeTexture.height * .25f), faceShapeTexture))
{
if (LipSyncLoaded.BlendShapeIndexes[id] > LipSyncLoaded.Skin.sharedMesh.blendShapeCount)
LipSyncLoaded.BlendShapeIndexes[id] = LipSyncLoaded.Skin.sharedMesh.blendShapeCount;
if(CurrentBlendShapeModel == null)
{
GameObject SelectedGO = LipSyncLoaded.gameObject;
SkinnedMeshRenderer currentSMR = SelectedGO.GetComponent<SkinnedMeshRenderer>();
Selection.activeGameObject = SelectedGO;
if (currentSMR != null)
{
if(LipSyncLoaded.FaceBones!=null && LipSyncLoaded.FaceBones.Length>0)
EnableBonePoseEdit(id);
if (LipSyncLoaded.BlendShapeIndexes[id] >= BlendShapeNames.Length - 1)
CurrentBlendShapeModel = MakeNewBlendShapeModel(GetPrestonBlairNamesFromIndex(id), -1);
else
CurrentBlendShapeModel = MakeNewBlendShapeModel(BlendShapeNames[LipSyncLoaded.BlendShapeIndexes[id]], LipSyncLoaded.BlendShapeIndexes[id]);
CurrentBlendShapeIndex = id;
if (flags == 0)
{
currentSMR.SetBlendShapeWeight(LipSyncLoaded.BlendShapeIndexes[id], 100);
currentSMR.enabled = true;
}
}
return;
}
else
{
BlendShapeManager.SetBlendShape(CurrentBlendShapeModel, LipSyncLoaded.Skin, BlendShapeType);
LipSyncLoaded.Skin.enabled = true;
if(LipSyncLoaded.BlendShapeIndexes[id]<LipSyncLoaded.Skin.sharedMesh.blendShapeCount)
LipSyncLoaded.Skin.SetBlendShapeWeight(LipSyncLoaded.BlendShapeIndexes[id], 0);
for (int i = 0; i < BlendShapeNames.Length; i++)
{
if (CurrentBlendShapeModel.name == BlendShapeNames[i])
{
LipSyncLoaded.BlendShapeIndexes[id] = i;
}
}
DestroyImmediate(CurrentBlendShapeModel);
Selection.activeGameObject = LipSyncLoaded.gameObject;
CurrentBlendShapeModel = null;
SetBonePose(id);
CurrentBlendShapeIndex = -1;
}
/*
if (Selection.activeGameObject != null)
{
MeshModifier mm = Selection.activeGameObject.GetComponent<MeshModifier>();
if (mm == null)
{
Selection.activeGameObject = LipSyncLoaded.gameObject;
GameObject SelectedGO = LipSyncLoaded.gameObject;
SkinnedMeshRenderer currentSMR = SelectedGO.GetComponent<SkinnedMeshRenderer>();
if (currentSMR != null)
{
EnableBonePoseEdit(id);
if (LipSyncLoaded.BlendShapeIndexes[id] >= BlendShapeNames.Length - 1)
CurrentBlendShapeModel = MakeNewBlendShapeModel(GetPrestonBlairNamesFromIndex(id), -1);
else
CurrentBlendShapeModel = MakeNewBlendShapeModel(BlendShapeNames[LipSyncLoaded.BlendShapeIndexes[id]], LipSyncLoaded.BlendShapeIndexes[id]);
CurrentBlendShapeIndex = id;
if (flags == 0)
{
currentSMR.SetBlendShapeWeight(LipSyncLoaded.BlendShapeIndexes[id], 100);
currentSMR.enabled = true;
}
}
return;
}
if (mm.TargetSkin != null)
{
CurrentSkinnedModel = mm.TargetSkin;
CurrentBlendShapeModel = mm.gameObject;
CurrentBlendShapeIndex = id;
}
if (CurrentBlendShapeModel != null)
{
BlendShapeManager.SetBlendShape(CurrentBlendShapeModel, CurrentSkinnedModel, BlendShapeType);
CurrentSkinnedModel.enabled = true;
CurrentSkinnedModel.SetBlendShapeWeight(LipSyncLoaded.BlendShapeIndexes[id], 0);
for (int i = 0; i < BlendShapeNames.Length; i++)
{
if (CurrentBlendShapeModel.name == BlendShapeNames[i])
{
LipSyncLoaded.BlendShapeIndexes[id] = i;
}
}
DestroyImmediate(CurrentBlendShapeModel);
Selection.activeGameObject = CurrentSkinnedModel.gameObject;
CurrentBlendShapeModel = null;
SetBonePose(id);
}
}
else
{
if (CurrentBlendShapeModel != null)
{
Selection.activeGameObject = CurrentBlendShapeModel;
return;
}
else if(LipSyncLoaded!=null)
Selection.activeGameObject = LipSyncLoaded.gameObject;
}*/
}
GUI.color = Color.white;
LipSyncLoaded.BlendShapeIndexes[id] = EditorGUI.Popup(new Rect(widthPad + 10, heightPad + 275, faceShapeTexture.width * .25f, 20), "", LipSyncLoaded.BlendShapeIndexes[id], BlendShapeNames);
if (LipSyncLoaded != null && LipSyncLoaded.FaceBones != null && LipSyncLoaded.FaceBones.Length > 0)
{
if (BonePoseIndex >= 0)
{
if(BonePoseIndex == id)
GUI.color = new Color(14f / 255f, 229f / 255f, 198f / 255f, 1f);
if (GUI.Button(new Rect(widthPad + 10, heightPad + 295, faceShapeTexture.width * .25f, 15), "Edit Bone Pose"))
{
SetBonePose(id);
}
GUI.color = Color.white;
}
else if (GUI.Button(new Rect(widthPad + 10, heightPad + 295, faceShapeTexture.width * .25f, 15), "Edit Bone Pose"))
{
EnableBonePoseEdit(id);
Selection.activeGameObject = LipSyncLoaded.FaceBones[0].gameObject;
}
}
}
private static void SetBonePose(int id)
{
// Set Bones
if (LipSyncLoaded.TransformStates.Count > 0)
{
for (int j = 0; j < LipSyncLoaded.FaceBones.Length; j++)
{
FaceControl fc = LipSyncLoaded.FaceBones[j].gameObject.GetComponent<FaceControl>();
if (fc != null)
DestroyImmediate(fc);
LipSyncLoaded.TransformStates[id].transformStates[j].position = LipSyncLoaded.FaceBones[j].localPosition;
LipSyncLoaded.TransformStates[id].transformStates[j].rotation = LipSyncLoaded.FaceBones[j].localRotation;
LipSyncLoaded.TransformStates[id].transformStates[j].scale = LipSyncLoaded.FaceBones[j].localScale;
// If Rest Pose, set initial position
if (id == 8)
{
TransformState ts = new TransformState(LipSyncLoaded.FaceBones[j].localPosition, LipSyncLoaded.FaceBones[j].localRotation, LipSyncLoaded.FaceBones[j].localScale);
LipSyncLoaded._currentTransforms.transformStates[j] = ts;
}
LipSyncLoaded.FaceBones[j].localPosition = LipSyncLoaded._currentTransforms.transformStates[j].position;
LipSyncLoaded.FaceBones[j].localRotation = LipSyncLoaded._currentTransforms.transformStates[j].rotation;
LipSyncLoaded.FaceBones[j].localScale = LipSyncLoaded._currentTransforms.transformStates[j].scale;
}
}
BonePoseIndex = -1;
}
private static void EnableBonePoseEdit(int id)
{
BonePoseIndex = id;
if (LipSyncLoaded.TransformStates.Count == 0 || LipSyncLoaded.FaceBones.Length != LipSyncLoaded.TransformStates[0].transformStates.Count || LipSyncLoaded._currentTransforms.transformStates.Count == 0)
{
Debug.Log("Initialising Bones");
LipSyncLoaded.TransformStates.Clear();
for (int i = 0; i < 9; i++)
{
ListTransformStates tl = new ListTransformStates();
for (int j = 0; j < LipSyncLoaded.FaceBones.Length; j++)
{
TransformState ts = new TransformState(LipSyncLoaded.FaceBones[j].localPosition, LipSyncLoaded.FaceBones[j].localRotation, LipSyncLoaded.FaceBones[j].localScale);
tl.transformStates.Add(ts);
if (i == 8)
LipSyncLoaded._currentTransforms.transformStates.Add(ts);
}
LipSyncLoaded.TransformStates.Add(tl);
}
}
for (int j = 0; j < LipSyncLoaded.FaceBones.Length; j++)
{
FaceControl fc = LipSyncLoaded.FaceBones[j].gameObject.GetComponent<FaceControl>();
if(fc==null)
LipSyncLoaded.FaceBones[j].gameObject.AddComponent<FaceControl>();
LipSyncLoaded.FaceBones[j].localPosition = LipSyncLoaded.TransformStates[id].transformStates[j].position;
LipSyncLoaded.FaceBones[j].localRotation = LipSyncLoaded.TransformStates[id].transformStates[j].rotation;
LipSyncLoaded.FaceBones[j].localScale = LipSyncLoaded.TransformStates[id].transformStates[j].scale;
if (id == 8)
{
TransformState ts = new TransformState(LipSyncLoaded.FaceBones[j].localPosition, LipSyncLoaded.FaceBones[j].localRotation, LipSyncLoaded.FaceBones[j].localScale);
LipSyncLoaded._currentTransforms.transformStates[j] = ts;
}
}
}
public void SetLipSync()
{
if (LipSyncLoaded != null)
{
if (!LipSyncLoaded.Initialized)
LipSyncLoaded.InitializeFromFile();
LipSyncLoaded.SetPhoneme(LipSyncLoaded.LipSyncIndex, TimeVal);
}
}
void Update()
{
if (!Application.isPlaying)
{
SetEditorDeltaTime();
if (Playing)
{
if (TimeVal < AudioClipLoaded.length)
{
TimeVal += editorDeltaTime;
}
else
{
Playing = false;
TimeVal = 0f;
}
}
if (Playing)
{
ShortStop -= Time.deltaTime;
SetLipSync();
Repaint();
}
else if (ShortStop >= 0f)
{
ShortStop -= Time.deltaTime;
}
else
{
if (AudioSourceLoaded != null)
AudioSourceLoaded.Stop();
Playing = false;
}
}
}
private void SetEditorDeltaTime()
{
if (lastTimeSinceStartup == 0f)
{
lastTimeSinceStartup = (float)EditorApplication.timeSinceStartup;
}
editorDeltaTime = (float)EditorApplication.timeSinceStartup - lastTimeSinceStartup;
lastTimeSinceStartup = (float)EditorApplication.timeSinceStartup;
}
private void DrawNodes()
{
if (_phonemeMarkers != null)
{
for (int i = 0; i < _phonemeMarkers.Count; i++)
{
_phonemeMarkers[i].Draw();
}
}
}
private void ProcessEvents(Event e)
{
switch (e.type)
{
case EventType.MouseDown:
if (e.button == 1)
{
ProcessContextMenu(e.mousePosition);
}
break;
case EventType.KeyDown:
if (e.keyCode == KeyCode.Space && !Application.isPlaying)
{
if (AudioSourceLoaded != null)
{
if (!Playing)
{
AudioSourceLoaded.time = TimeVal;
AudioSourceLoaded.Play();
Playing = true;
}
else
{
AudioSourceLoaded.Stop();
ShortStop = -1f;
Playing = false;
}
}
}
break;
}
}
private void ProcessNodeEvents(Event e)
{
if (_phonemeMarkers != null)
{
for (int i = _phonemeMarkers.Count - 1; i >= 0; i--)
{
bool guiChanged = _phonemeMarkers[i].ProcessEvents(e);
if (guiChanged)
{
GUI.changed = true;
break;
}
}
}
}
private void ProcessContextMenu(Vector2 mousePosition)
{
GenericMenu genericMenu = new GenericMenu();
genericMenu.AddItem(new GUIContent("MBP"), false, () => OnClickAddNode(mousePosition, "A"));
genericMenu.AddItem(new GUIContent("etc"), false, () => OnClickAddNode(mousePosition, "B"));
genericMenu.AddItem(new GUIContent("E"), false, () => OnClickAddNode(mousePosition, "C"));
genericMenu.AddItem(new GUIContent("AI"), false, () => OnClickAddNode(mousePosition, "D"));
genericMenu.AddItem(new GUIContent("O"), false, () => OnClickAddNode(mousePosition, "E"));
genericMenu.AddItem(new GUIContent("U"), false, () => OnClickAddNode(mousePosition, "F"));
genericMenu.AddItem(new GUIContent("FV"), false, () => OnClickAddNode(mousePosition, "G"));
genericMenu.AddItem(new GUIContent("L"), false, () => OnClickAddNode(mousePosition, "H"));
genericMenu.AddItem(new GUIContent("rest"), false, () => OnClickAddNode(mousePosition, "X"));
genericMenu.AddItem(new GUIContent("Delete"), false, () => DeleteNode(mousePosition));
int bsCount = LipSyncLoaded.Skin.sharedMesh.blendShapeCount;
for(int id =0;id< bsCount;id++)
{
if (!LipSyncLoaded.BlendShapeIndexes.Contains(id))
{
int index = id;
string bsName = LipSyncLoaded.Skin.sharedMesh.GetBlendShapeName(id);
genericMenu.AddItem(new GUIContent("All Blend Shapes/" + bsName + " (" + id+ ")"), false, () => OnClickAddNode(mousePosition, bsName, index));
}
}
genericMenu.ShowAsContext();
}
private void DeleteNode(Vector2 mousePosition)
{
for (int i = 0; i < _phonemeMarkers.Count; i++)
{
if(_phonemeMarkers[i].IsMarkerUnderMouse(mousePosition))
{
_phonemeMarkers.RemoveAt(i);
break;
}
/*if (CurrentSelectedPhonemeMarker >= 0 && i == CurrentSelectedPhonemeMarker)
{
_phonemeMarkers.RemoveAt(i);
break;
}*/
/*else if (_phonemeMarkers[i].rect.Contains(mousePosition))
{
_phonemeMarkers.RemoveAt(i);
break;
}*/
}
RefreshNodes(mousePosition);
Repaint();
SetLipSync();
}
private void OnClickAddNode(Vector2 mousePosition, string shapeName, int blendShapeIndex = -1)
{
if (_phonemeMarkers == null)
{
_phonemeMarkers = new List<PhonemeMarker>();
}
float markerPos = ((mousePosition.x - WaveFormPosX) / (float)WaveFormWidth) * (float)AudioClipLoaded.length;
// check if hovering over phoneme
for (int i = 0; i < _phonemeMarkers.Count; i++)
{
if(_phonemeMarkers[i].IsMarkerUnderMouse(mousePosition))
{
markerPos = ((_phonemeMarkers[i].rect.center.x - WaveFormPosX) / (float)WaveFormWidth) * (float)AudioClipLoaded.length;
DeleteNode(mousePosition);
RefreshNodes(mousePosition);
}
}
_phonemeMarkers.Add(new PhonemeMarker(new Vector2(markerPos, WaveFormPosY + 100), 70, 70, _phonemeMarkerStyle, shapeName, markerPos - 0.05f, markerPos + 0.05f, 1f, _phonemeMarkers.Count, blendShapeIndex));
CurrentSelectedPhonemeMarker = _phonemeMarkers.Count - 1;
RefreshNodes(mousePosition);
Repaint();
SetLipSync();
}
private void ReloadNodes(Vector2 mousePosition)
{
if (AudioSourceLoaded && LipSyncLoaded && AudioClipLoaded && LipSyncLoaded.LipSyncFiles.Length > 0)
{
if (_phonemeMarkers == null)
{
_phonemeMarkers = new List<PhonemeMarker>();
}
_phonemeMarkers.Clear();
string[] _phonemeArray = LipSyncLoaded.GetPhonemes(LipSyncLoaded.LipSyncIndex);
for (int i = 0; i < _phonemeArray.Length; i++)
{
string[] vals = _phonemeArray[i].Split(';');
float timeVal = (float.Parse(vals[1]) + float.Parse(vals[0])) * .5f;
_phonemeMarkers.Add(new PhonemeMarker(new Vector2(WaveFormPosX - 35 + (timeVal / AudioClipLoaded.length) * WaveFormWidth, WaveFormPosY + 100), 70, 70, _phonemeMarkerStyle, vals[2], float.Parse(vals[0]), float.Parse(vals[1]), float.Parse(vals[3]), i, int.Parse(vals[4])));
}
Debug.Log("Loaded " + LipSyncLoaded.LipSyncFiles[LipSyncLoaded.LipSyncIndex].name);
}
}
private void RefreshNodes(Vector2 mousePosition)
{
if (AudioSourceLoaded && LipSyncLoaded && AudioClipLoaded)
{
if (_phonemeMarkers == null || _phonemeMarkers.Count == 0)
{
//ReloadNodes(mousePosition);
//DrawNodes();
}
else
{
for (int i = _phonemeMarkers.Count - 1; i >= 0; i--)
{
float timeVal = (_phonemeMarkers[i].Start + _phonemeMarkers[i].End) * 0.5f;// (float.Parse(vals[1]) + float.Parse(vals[0]))/2f;
_phonemeMarkers[i] = (new PhonemeMarker(new Vector2(WaveFormPosX - 35 + (timeVal / AudioClipLoaded.length) * WaveFormWidth, WaveFormPosY + 100), 70, 70, _phonemeMarkerStyle, _phonemeMarkers[i].Label, _phonemeMarkers[i].Start, _phonemeMarkers[i].End, _phonemeMarkers[i].Strength, i, _phonemeMarkers[i].BlendShapeID));
}
}
if (_phonemeMarkers != null && _phonemeMarkers.Count > 0)
LipSyncLoaded.InitializeFromData(MakeFaceShapeData(_phonemeMarkers), LipSyncLoaded.LipSyncIndex);
}
}
public ListFaceShapes MakeFaceShapeData(List<PhonemeMarker> pms)
{
ListFaceShapes FaceShapeData = new ListFaceShapes();
for (int t = 0; t < pms.Count; t++)
{
FaceShapeData.Add(new FaceShape(pms[t].Start, pms[t].End, pms[t].Label, pms[t].Strength, pms[t].BlendShapeID ));
}
return FaceShapeData;
}
static void MakeThisABlendShapeModel()
{
GameObject SelectedGO = Selection.activeGameObject;
SkinnedMeshRenderer smr = SelectedGO.GetComponent<SkinnedMeshRenderer>();
CurrentSkinnedModel = smr;
MeshModifier meshModifier = SelectedGO.AddComponent<MeshModifier>();
meshModifier.TargetSkin = smr;
}
static GameObject MakeNewBlendShapeModel(string blendShapeName, int index = 0)
{
GameObject SelectedGO = Selection.activeGameObject;
SkinnedMeshRenderer currentSMR = SelectedGO.GetComponent<SkinnedMeshRenderer>();
if (currentSMR == null)
{
MeshRenderer mr = SelectedGO.GetComponent<MeshRenderer>();
if (mr == null)
{
Debug.LogWarning("Please select a mesh");
return null;
}
else
{
currentSMR = SelectedGO.AddComponent<SkinnedMeshRenderer>();
}
}
CurrentSkinnedModel = currentSMR;
currentSMR.enabled = false;
GameObject newBlendShapeGO = new GameObject();
newBlendShapeGO.name = blendShapeName;
if (BlendShapeType == 1)
{
SkinnedMeshRenderer smr = newBlendShapeGO.AddComponent<SkinnedMeshRenderer>();
MakeBlendShapeMesh(SelectedGO.GetComponent<SkinnedMeshRenderer>().sharedMesh, index, currentSMR, smr, null, null);
}
else
{
MeshRenderer mrNew = newBlendShapeGO.AddComponent<MeshRenderer>();
MeshFilter mf = newBlendShapeGO.AddComponent<MeshFilter>();
MakeBlendShapeMesh(SelectedGO.GetComponent<SkinnedMeshRenderer>().sharedMesh, index, currentSMR,null, mrNew, mf);
}
newBlendShapeGO.transform.position = SelectedGO.transform.position;
newBlendShapeGO.transform.rotation = SelectedGO.transform.rotation;
newBlendShapeGO.transform.localScale = SelectedGO.transform.localScale;
MeshModifier meshModifier = newBlendShapeGO.AddComponent<MeshModifier>();
meshModifier.TargetSkin = currentSMR;
meshModifier.BlendShapeType = BlendShapeType;
meshModifier.ConnectedVertexThreshold = 0f;
Selection.activeGameObject = newBlendShapeGO;
return newBlendShapeGO;
}
static public Mesh MakeBlendShapeMesh(Mesh mesh, int index,SkinnedMeshRenderer currentSMR, SkinnedMeshRenderer smr, MeshRenderer mr, MeshFilter mf)
{
Mesh newMesh = new Mesh();
if (BlendShapeType == 2)
currentSMR.BakeMesh(newMesh);
else
newMesh.vertices = currentSMR.sharedMesh.vertices;
Vector3[] deltas = new Vector3[mesh.vertexCount];
Vector3[] deltaNormals = new Vector3[mesh.vertexCount];
Vector3[] deltaTangents = new Vector3[mesh.vertexCount];
if (index >= 0)
{
currentSMR.SetBlendShapeWeight(index, 0);
mesh.GetBlendShapeFrameVertices(index, 0, deltas, deltaNormals, deltaTangents);
int vertCount = mesh.vertexCount;
if (BlendShapeType == 2)
{
Vector3[] verts = newMesh.vertices;
Vector3[] normals = newMesh.normals;
for (int i = 0; i < vertCount; i++)
{
deltas[i] += verts[i];
}
}
else
{
Vector3[] verts = mesh.vertices;
Vector3[] normals = mesh.normals;
for (int i = 0; i < vertCount; i++)
{
deltas[i] += verts[i];
}
}
newMesh.vertices = deltas;
}
newMesh.colors = mesh.colors;
newMesh.normals = mesh.normals;
newMesh.uv = mesh.uv;
newMesh.bindposes = mesh.bindposes;
newMesh.boneWeights = mesh.boneWeights;
newMesh.tangents = mesh.tangents;
newMesh.subMeshCount = selectedOptions.Count;// mesh.subMeshCount;
Material[] mats = new Material[selectedOptions.Count];
for (int i = 0; i < selectedOptions.Count; i++)
{
newMesh.SetTriangles(mesh.GetTriangles(selectedOptions[i]), i);
mats[i] = currentSMR.sharedMaterials[selectedOptions[i]];
}
/*
newMesh.subMeshCount = mesh.subMeshCount;
for (int i = 0; i < mesh.subMeshCount; i++)
{
newMesh.SetTriangles(mesh.GetTriangles(i), i);
}*/
if (smr == null)
{
mr.sharedMaterials = mats;
mf.sharedMesh = newMesh;
}
else
{
smr.sharedMaterials = mats;
smr.sharedMesh = newMesh;
smr.bones = currentSMR.bones;
}
return newMesh;
}
static void FocusCameraOnGameObject(Camera c, GameObject go)
{
Bounds b = go.GetComponent<Renderer>().bounds;
Vector3 max = b.size;
float radius = Mathf.Max(max.x, Mathf.Max(max.y, max.z));
float dist = 0.666f * radius / (Mathf.Sin(c.fieldOfView * Mathf.Deg2Rad));
Vector3 pos = Vector3.forward * dist + b.center;
c.transform.position = pos;
c.transform.LookAt(b.center);
}
public static Texture2D TakeScreenShot(Camera viewCam = null)
{
if (viewCam == null)
viewCam = SceneView.currentDrawingSceneView.camera;
return Screenshot(viewCam);
}
public static void SetEditorData()
{
string savedData = blendShapeTextures.Count + ";";
for (int i = 0; i < blendShapeTextures.Count; i++)
{
savedData += blendShapeTextures[i] + ";";
}
EditorPrefs.SetString("_PuppetFaceBlendShapeTexturePaths", savedData);
}
public static void GetEditorData()
{
string savedData = EditorPrefs.GetString("_PuppetFaceBlendShapeTexturePaths");
if (savedData != "")
{
string[] savedDataSplit = savedData.Split(';');
blendShapeTextures = new List<string>();
blendShapeTextures.Clear();
if (savedDataSplit.Length > 0)
{
int numberTextures = int.Parse(savedDataSplit[0]);
if (numberTextures > 0)
{
for (int i = 0; i < numberTextures; i++)
{
blendShapeTextures.Add(savedDataSplit[i + 1]);
}
}
}
}
}
static Texture2D Screenshot(Camera cam)
{
if (cam == null)
{
Debug.LogWarning("Need a preview camera on the selected BlendShape");
return null;
}
int resWidth = 408; //cam.pixelWidth;
int resHeight = 334;// cam.pixelHeight;
resWidth = (int)(float)(resWidth);
resHeight = (int)(float)(resHeight);
RenderTexture rt = new RenderTexture(resWidth, resHeight, 32);
cam.targetTexture = rt;
Texture2D screenShot = new Texture2D(resWidth, resHeight, TextureFormat.ARGB32, false);
cam.Render();
RenderTexture.active = rt;
screenShot.ReadPixels(new Rect(0, 0, resWidth, resHeight), 0, 0);
screenShot.Apply();
cam.targetTexture = null;
RenderTexture.active = null; // JC: added to avoid errors
DestroyImmediate(rt);
return screenShot;
}
public static Texture2D SaveScreenshotToFile(string fileName, Camera cam)
{
Texture2D screenShot = Screenshot(cam);
byte[] bytes = screenShot.EncodeToPNG();
Debug.Log("Saving " + fileName);
System.IO.File.WriteAllBytes(fileName, bytes);
return screenShot;
}
public Texture2D PaintWaveformSpectrum(AudioClip audio, float saturation, Rect rect, Color col)
{
int widthPad = (int)rect.min.x;
int heightPad = (int)rect.min.y;
int width = (int)rect.width;
int height = (int)rect.height;
int windowWidth = (int)_puppetFaceEditor.position.width - 20;
WaveFormWidth = Mathf.Max(WaveFormWidth, windowWidth);
if (AudioSourceLoaded != null && AudioClipLoaded != null && LipSyncLoaded != null)
{
if (Event.current.button == 2)
{
if (Mathf.Abs(Event.current.delta.x) > 0)
{
WaveFormPosX += (int)(Event.current.delta.x * .5f);
WaveFormPosX = (int)Mathf.Clamp(WaveFormPosX, (int)_puppetFaceEditor.position.width - WaveFormWidth - 20, 1);
RefreshNodes(Vector2.zero);
Repaint();
}
}
if (Event.current.type == EventType.ScrollWheel)
{
if (windowWidth - WaveFormWidth <= 0)
{
WaveFormWidth -= 100 * (int)Event.current.delta.y;
WaveFormWidth = Mathf.Max(WaveFormWidth, windowWidth);
WaveFormPosX = (int)Mathf.Clamp(WaveFormPosX, (int)_puppetFaceEditor.position.width - WaveFormWidth - 20, 1);
RefreshNodes(Vector2.zero);
Repaint();
}
}
}
int sampleCountOriginal = 1;
int sampleCount = 1;
if (audio != null)
{
sampleCountOriginal = audio.samples;
}
sampleCount = (int)((int)(audio.channels * sampleCountOriginal) * (((float)windowWidth) / (float)WaveFormWidth));
int startVal = -1 * (int)(sampleCountOriginal * (((float)WaveFormPosX) / (float)WaveFormWidth));
if (startVal < 0)
startVal = 0;
Texture2D tex = new Texture2D(windowWidth, height, TextureFormat.RGBA32, false);
float[] samples = new float[sampleCount];
float[] waveform = new float[windowWidth];
int packSize = 1;
if (audio != null)
{
if (audio.loadType == AudioClipLoadType.DecompressOnLoad)
{
audio.GetData(samples, startVal);
}
packSize = (sampleCount / windowWidth) + 1;
}
int s = 0;
for (int i = 0; i < sampleCount; i += packSize)
{
waveform[s] = Mathf.Abs(samples[i]);
s++;
}
for (int x = 0; x < windowWidth; x++)
{
for (int y = 0; y < height; y++)
{
tex.SetPixel(x, y, new Color(0.35f, 0.35f, 0.35f, 1f));
}
}
for (int x = 0; x < waveform.Length; x++)
{
for (int y = 0; y <= waveform[x] * ((float)height); y++)
{
tex.SetPixel(x, (height / 2) + y, col);
tex.SetPixel(x, (height / 2) - y, col);
}
}
tex.Apply();
GUI.DrawTexture(new Rect(new Vector2(0, heightPad + 20), new Vector2(Mathf.Min(WaveFormWidth, (int)_puppetFaceEditor.position.width - 20), 100)), tex);
if (audio != null)
{
for (int x = 0; x < audio.length; x++)
{
float val = ((float)x / (float)audio.length);
Handles.DrawLine(new Vector3(WaveFormPosX + (float)val * WaveFormWidth, rect.min.y), new Vector3(widthPad + (float)val * WaveFormWidth, rect.min.y + 120));
string timeEncoded = ((float)x).ToString("00") + ":00";
GUI.Label(new Rect(new Vector2(WaveFormPosX + (float)val * WaveFormWidth, rect.min.y), 50 * Vector2.one), timeEncoded, _defaultStyle);
float offset = (WaveFormWidth / (audio.length * 30f));
for (int v = 0; v < 30; v++)
{
if (v % 30 == 0)
Handles.color = new Color(1, 1, 1, .5f);
else if (v % 30 == 15)
Handles.color = new Color(1, 1, 1, .25f);
else
Handles.color = new Color(1, 1, 1, .05f);
Handles.DrawLine(new Vector3(WaveFormPosX + (float)val * WaveFormWidth + v * offset, rect.min.y + 10), new Vector3(WaveFormPosX + (float)val * WaveFormWidth + v * offset, rect.min.y + 120));
}
Handles.color = new Color(1, 1, 1, 1f);
int linePos = (int)((TimeVal * WaveFormWidth) / AudioClipLoaded.length);
Handles.DrawLine(new Vector3(WaveFormPosX + linePos, heightPad + 20), new Vector3(WaveFormPosX + linePos, heightPad + 120));
Handles.DrawLine(new Vector3(WaveFormPosX + linePos + 1, heightPad + 20), new Vector3(WaveFormPosX + linePos + 1, heightPad + 120));
}
}
return tex;
}
private static string RecursivelyFindFolderPath()
{
DirectoryInfo directoryInfo = new DirectoryInfo(Application.dataPath);
DirectoryInfo[] dirInfos = directoryInfo.GetDirectories("*", SearchOption.AllDirectories);
foreach (DirectoryInfo d in dirInfos)
{
if (d.Name == "PuppetFace" && d.Parent.Name != "Gizmos")
return d.FullName;
}
return "";
}
}
}