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

337 lines
11 KiB
C#

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEngine.UI;
using System.IO;
namespace PuppetFace
{
[CustomEditor(typeof(PerformanceCapture))]
public class PerformanceCaptureEditor : Editor
{
public PerformanceCapture pc;
public bool Open = false;
public bool OpenCalibrating = false;
public bool Oh = false;
public bool Corners = false;
public bool HeadRot = false;
public bool Jaw = false;
public bool EyeBrows = false;
private static string _puppetFacePath;
void OnEnable()
{
_puppetFacePath = "Assets" + RecursivelyFindFolderPath().Substring(Application.dataPath.Length);
pc = (PerformanceCapture)target;
if (pc.faces == null)
{
TextAsset t = AssetDatabase.LoadAssetAtPath(_puppetFacePath +"/Scripts/faceDefaults.xml", typeof(TextAsset)) as TextAsset;
pc.faces = t;
}
if (pc.eyes == null)
{
TextAsset t = AssetDatabase.LoadAssetAtPath(_puppetFacePath +"/Scripts/eyeDefaults.xml", typeof(TextAsset)) as TextAsset;
pc.eyes = t;
}
if (pc.shapes == null)
{
TextAsset t = AssetDatabase.LoadAssetAtPath(_puppetFacePath +"/Scripts/shape_predictor_68_face_landmarks.bytes", typeof(TextAsset)) as TextAsset;
pc.shapes = t;
}
if (pc.Surface == null)
{
GameObject rawImageGO = new GameObject("Performance Feed");
GameObject newCanvas = new GameObject("Performance Canvas");
rawImageGO.AddComponent<RawImage>();
Canvas canv = newCanvas.AddComponent<Canvas>();
canv.renderMode = RenderMode.ScreenSpaceCamera;
canv.worldCamera = Camera.main;
rawImageGO.transform.SetParent(newCanvas.transform);
rawImageGO.GetComponent<RectTransform>().anchoredPosition3D = Vector3.zero;
rawImageGO.GetComponent<RectTransform>().localScale = Vector3.one*.5f;
rawImageGO.transform.localRotation = Quaternion.identity;
pc.Surface = rawImageGO;
}
if (pc.Skin == null && pc.GetComponent<SkinnedMeshRenderer>()!=null)
{
pc.Skin = pc.GetComponent<SkinnedMeshRenderer>();
}
}
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;
}
public override void OnInspectorGUI()
{
GUILayout.Space(10);
WebCamDevice[] devices = WebCamTexture.devices;
string[] deviceNames = new string[devices.Length];
for (int i = 0; i < devices.Length; i++)
{
deviceNames[i] = devices[i].name;
}
pc.DeviceIndex = EditorGUILayout.Popup(pc.DeviceIndex, deviceNames);
string[] micDevices = Microphone.devices;
pc.MicrophoneDeviceIndex = EditorGUILayout.Popup(pc.MicrophoneDeviceIndex, micDevices);
if(micDevices.Length>0)
Microphone.GetDeviceCaps(micDevices[pc.DeviceIndex], out pc.MinFrequency, out pc.MaxFrequency);
if (pc.MinFrequency == 0 && pc.MaxFrequency == 0)
{
pc.MaxFrequency = 44100;
}
string LogoPath = _puppetFacePath +"/Textures/GUI/PuppetFaceLogo.png";
Texture LogoAsset = AssetDatabase.LoadAssetAtPath(LogoPath, typeof(Texture)) as Texture;
GUILayout.BeginHorizontal();
GUILayout.BeginVertical();
pc.Skin = (SkinnedMeshRenderer)EditorGUILayout.ObjectField("Skin", pc.Skin, typeof(SkinnedMeshRenderer), true);
pc.Anim = (Animator)EditorGUILayout.ObjectField("Animator", pc.Anim, typeof(Animator), true);
GUILayout.EndVertical();
GUILayout.Label( LogoAsset, GUILayout.Width(40), GUILayout.Height(40));
GUILayout.EndHorizontal();
if (!pc.CalibrateBase)
{
if (GUILayout.Button("Calibrate Default Pose", GUILayout.Width(100), GUILayout.Height(15), GUILayout.ExpandHeight(false), GUILayout.ExpandWidth(true)))
{
pc.CalibrateBase = true;
}
}
else
{
GUI.color = Color.green;
if (GUILayout.Button("Stop Calibrating Default Pose", GUILayout.Width(100), GUILayout.Height(15), GUILayout.ExpandHeight(false), GUILayout.ExpandWidth(true)))
{
pc.CalibrateBase = false;
}
GUI.color = Color.white;
}
pc.HeadRot = EditorGUILayout.Toggle("Head Rotation", pc.HeadRot);
if (pc.HeadRot)
{
GUILayout.BeginVertical(EditorStyles.helpBox);
HeadRot = EditorGUILayout.Foldout(HeadRot, "Head Rotation");
if (HeadRot)
{
EditorGUI.BeginChangeCheck();
pc.RotBone = (Transform)EditorGUILayout.ObjectField("Head Bone", pc.RotBone, typeof(Transform), true);
if (EditorGUI.EndChangeCheck())
{
pc.HeadForwardBaked = pc.RotBone.rotation;
}
pc.RotationLimits = EditorGUILayout.Vector3Field("Rotation Amount", pc.RotationLimits);
EditorGUI.BeginChangeCheck();
pc.HeadSmoothing = EditorGUILayout.IntSlider(new GUIContent("Smoothing"), pc.HeadSmoothing, 1, 20);
if (EditorGUI.EndChangeCheck())
{
pc.rotationAverage.Clear();
}
}
GUILayout.EndVertical();
}
pc.Open = EditorGUILayout.Toggle("Open", pc.Open);
if (pc.Open && pc.Skin != null)
{
GUILayout.BeginVertical(EditorStyles.helpBox);
Open = EditorGUILayout.Foldout(Open, "Open");
if (Open)
{
pc.OpenMinMax = EditorGUILayout.Vector2Field("Open Min Max", pc.OpenMinMax);
if (!pc.CalibrateOpen)
{
if (GUILayout.Button("Calibrate Open Pose", GUILayout.Width(100), GUILayout.Height(15), GUILayout.ExpandHeight(false), GUILayout.ExpandWidth(true)))
{
pc.CalibrateOpen = true;
}
}
else
{
GUI.color = Color.green;
if (GUILayout.Button("Stop Calibrating Open Pose", GUILayout.Width(100), GUILayout.Height(15), GUILayout.ExpandHeight(false), GUILayout.ExpandWidth(true)))
{
pc.CalibrateOpen = false;
}
GUI.color = Color.white;
}
pc.OpenMouthIndex = EditorGUILayout.Popup("Open Blend Shape", pc.OpenMouthIndex, GetArrayBlendShapes(pc.Skin));
EditorGUI.BeginChangeCheck();
pc.JawBone = (Transform)EditorGUILayout.ObjectField("Jaw Bone", pc.JawBone, typeof(Transform), true);
if (EditorGUI.EndChangeCheck())
{
pc.JawDefault = pc.JawBone.localRotation;
}
if (pc.JawBone != null)
{
if (GUILayout.Button("Set Open Pose", GUILayout.Width(100), GUILayout.Height(15), GUILayout.ExpandHeight(false), GUILayout.ExpandWidth(true)))
{
pc.JawOpen = pc.JawBone.localRotation;
pc.JawBone.localRotation = pc.JawDefault;
}
}
EditorGUI.BeginChangeCheck();
pc.OpenSmoothing = EditorGUILayout.IntSlider(new GUIContent("Smoothing"), pc.OpenSmoothing, 1, 20);
if (EditorGUI.EndChangeCheck())
{
pc.OpenBlendFrameCount = pc.OpenSmoothing;
pc.OpenMinMaxAverage.Clear();
}
}
GUILayout.EndVertical();
}
pc.Oh = EditorGUILayout.Toggle("Oh", pc.Oh);
if (pc.Oh && pc.Skin != null)
{
GUILayout.BeginVertical(EditorStyles.helpBox);
Oh = EditorGUILayout.Foldout(Oh, "Oh");
if (Oh)
{
pc.OhMinMax = EditorGUILayout.Vector2Field("Oh Min Max", pc.OhMinMax);
if (!pc.CalibrateOh)
{
if (GUILayout.Button("Calibrate Oh Pose", GUILayout.Width(100), GUILayout.Height(15), GUILayout.ExpandHeight(false), GUILayout.ExpandWidth(true)))
{
pc.CalibrateOh = true;
}
}
else
{
GUI.color = Color.green;
if (GUILayout.Button("Stop Calibrating Oh Pose", GUILayout.Width(100), GUILayout.Height(15), GUILayout.ExpandHeight(false), GUILayout.ExpandWidth(true)))
{
pc.CalibrateOh = false;
}
GUI.color = Color.white;
}
pc.OhMouthIndex = EditorGUILayout.Popup("Oh Blend Shape", pc.OhMouthIndex, GetArrayBlendShapes(pc.Skin));
EditorGUI.BeginChangeCheck();
pc.OhSmoothing = EditorGUILayout.IntSlider(new GUIContent("Smoothing"), pc.OhSmoothing, 1, 20);
if (EditorGUI.EndChangeCheck())
{
pc.OhMinMaxAverage.Clear();
}
}
GUILayout.EndVertical();
}
CreatePoseGUI("Smile", ref pc.Corners, ref Corners, ref pc.CornersMinMax, ref pc.CalibrateCorners, ref pc.CornersMouthIndex, ref pc.CornersSmoothing,ref pc.CornersMinMaxAverage);
CreatePoseGUI("Eyebrows", ref pc.EyeBrows, ref EyeBrows, ref pc.EyeBrowsMinMax, ref pc.CalibrateEyeBrows, ref pc.EyeBrowsIndex, ref pc.EyeBrowsSmoothing, ref pc.EyeBrowsMinMaxAverage);
if (!pc.isRecording)
{
if (GUILayout.Button("Capture", GUILayout.Width(100), GUILayout.Height(25), GUILayout.ExpandHeight(false), GUILayout.ExpandWidth(true)))
{
pc.isRecording = true;
pc.StartRecording();
}
}
else
{
GUI.color = Color.green;
if (GUILayout.Button("Stop Capture", GUILayout.Width(100), GUILayout.Height(25), GUILayout.ExpandHeight(false), GUILayout.ExpandWidth(true)))
{
pc.isRecording = false;
pc.EndRecording();
}
GUI.color = Color.white;
}
}
public void CreatePoseGUI(string name,ref bool toggle, ref bool toggleFoldout, ref Vector2 minMax, ref bool Calibrate, ref int BlendShapeIndex, ref int Smoothing, ref Queue<float> minMaxAverage)
{
toggle = EditorGUILayout.Toggle(name, toggle);
if (toggle && pc.Skin != null)
{
GUILayout.BeginVertical(EditorStyles.helpBox);
toggleFoldout = EditorGUILayout.Foldout(toggleFoldout, name);
if (toggleFoldout)
{
minMax = EditorGUILayout.Vector2Field(name +" MinMax", minMax);
if (!Calibrate)
{
if (GUILayout.Button("Calibrate " + name + " Pose", GUILayout.Width(100), GUILayout.Height(15), GUILayout.ExpandHeight(false), GUILayout.ExpandWidth(true)))
{
Calibrate = true;
}
}
else
{
GUI.color = Color.green;
if (GUILayout.Button("Stop Calibrating " + name + " Pose", GUILayout.Width(100), GUILayout.Height(15), GUILayout.ExpandHeight(false), GUILayout.ExpandWidth(true)))
{
Calibrate = false;
}
GUI.color = Color.white;
}
BlendShapeIndex = EditorGUILayout.Popup(name + " Blend Shape", BlendShapeIndex, GetArrayBlendShapes(pc.Skin));
EditorGUI.BeginChangeCheck();
Smoothing = EditorGUILayout.IntSlider(new GUIContent("Smoothing"), Smoothing, 1, 20);
if (EditorGUI.EndChangeCheck())
{
minMaxAverage.Clear();
}
}
GUILayout.EndVertical();
}
}
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 "";
}
}
}