132 lines
6.3 KiB
C#
132 lines
6.3 KiB
C#
|
using System.Collections.Generic;
|
|||
|
using System.Linq;
|
|||
|
using ABI.CCK.Components;
|
|||
|
using UnityEditor;
|
|||
|
using UnityEngine;
|
|||
|
|
|||
|
namespace ABI.CCK.Scripts.Editor
|
|||
|
{
|
|||
|
[CustomEditor(typeof(ABI.CCK.Components.CVRFaceTracking))]
|
|||
|
public class CCK_CVRFaceTrackingEditor : UnityEditor.Editor
|
|||
|
{
|
|||
|
private CVRFaceTracking _faceTracking;
|
|||
|
|
|||
|
public override void OnInspectorGUI()
|
|||
|
{
|
|||
|
if (_faceTracking == null) _faceTracking = (CVRFaceTracking) target;
|
|||
|
|
|||
|
_faceTracking.GetBlendShapeNames();
|
|||
|
|
|||
|
_faceTracking.UseFacialTracking = EditorGUILayout.Toggle("Enable Facial Tracking", _faceTracking.UseFacialTracking);
|
|||
|
|
|||
|
_faceTracking.BlendShapeStrength = EditorGUILayout.Slider("Blend Shape Weight", _faceTracking.BlendShapeStrength, 50f, 500f);
|
|||
|
|
|||
|
_faceTracking.FaceMesh = (SkinnedMeshRenderer)EditorGUILayout.ObjectField("Face Mesh", _faceTracking.FaceMesh, typeof(SkinnedMeshRenderer), true);
|
|||
|
|
|||
|
for (int i = 0; i < CVRFaceTracking.FaceBlendShapeNames.Length; i++)
|
|||
|
{
|
|||
|
int current = 0;
|
|||
|
for (int j = 0; j < _faceTracking.BlendShapeNames.Count; ++j)
|
|||
|
if (_faceTracking.FaceBlendShapes[i] == _faceTracking.BlendShapeNames[j])
|
|||
|
current = j;
|
|||
|
|
|||
|
int viseme = EditorGUILayout.Popup(CVRFaceTracking.FaceBlendShapeNames[i], current, _faceTracking.BlendShapeNames.ToArray());
|
|||
|
_faceTracking.FaceBlendShapes[i] = _faceTracking.BlendShapeNames[viseme];
|
|||
|
}
|
|||
|
|
|||
|
if (GUILayout.Button("Auto select Blendshapes"))
|
|||
|
{
|
|||
|
_faceTracking.FindVisemes();
|
|||
|
}
|
|||
|
|
|||
|
EditorGUILayout.BeginVertical("HelpBox");
|
|||
|
EditorGUILayout.LabelField("Face Tracking ");
|
|||
|
EditorGUILayout.BeginVertical("GroupBox");
|
|||
|
|
|||
|
_faceTracking.enableOverdriveBlendShapes = EditorGUILayout.Toggle("Enable Overdrive", _faceTracking.enableOverdriveBlendShapes);
|
|||
|
EditorGUILayout.HelpBox("By enabling overdrive the system expects the blendshapes to be at 500% when fully set. You can use the button below to generate 500% versions of the currently selected blendshapes.", MessageType.Info);
|
|||
|
|
|||
|
if (GUILayout.Button("Generate overdrive Blendshapes (Experimental)"))
|
|||
|
{
|
|||
|
GenerateOverdriveBlendShapes();
|
|||
|
}
|
|||
|
|
|||
|
EditorGUILayout.EndVertical();
|
|||
|
EditorGUILayout.EndVertical();
|
|||
|
|
|||
|
EditorGUILayout.Space();
|
|||
|
|
|||
|
EditorGUILayout.HelpBox("We have prepared a way to generate a simple facial tracker support for your avatars without any requirement to use a 3D model software. For a more in-depth / detailed support, please create the required blendshapes using a 3D modeling software. More information can be found in our documentation.", MessageType.Info);
|
|||
|
|
|||
|
if (GUILayout.Button("Open Blendshape Generator (Experimental)"))
|
|||
|
{
|
|||
|
CCK_FaceTrackingUtilities window = (CCK_FaceTrackingUtilities)EditorWindow.GetWindow (typeof(CCK_FaceTrackingUtilities), true, "CCK :: Face Tracking Utilities");
|
|||
|
window.Avatar = _faceTracking.gameObject.GetComponent<CVRAvatar>();
|
|||
|
if (window.Avatar == null) window.Avatar = _faceTracking.gameObject.GetComponentInParent<CVRAvatar>();
|
|||
|
window.FaceTracking = _faceTracking;
|
|||
|
window.Tab = 1;
|
|||
|
window.Show();
|
|||
|
}
|
|||
|
|
|||
|
if (GUILayout.Button("Reset to original Mesh"))
|
|||
|
{
|
|||
|
if (_faceTracking.OriginalMesh != null)
|
|||
|
{
|
|||
|
_faceTracking.FaceMesh.sharedMesh = _faceTracking.OriginalMesh;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public void GenerateOverdriveBlendShapes()
|
|||
|
{
|
|||
|
Mesh mesh;
|
|||
|
CVRAvatar avatar = _faceTracking.GetComponentInParent<CVRAvatar>();
|
|||
|
|
|||
|
if (_faceTracking.FaceMesh.sharedMesh != _faceTracking.OriginalMesh)
|
|||
|
{
|
|||
|
mesh = _faceTracking.FaceMesh.sharedMesh.Copy();
|
|||
|
|
|||
|
string pathToCurrentFolder = "Assets/FaceTracking.Generated";
|
|||
|
if (!AssetDatabase.IsValidFolder(pathToCurrentFolder)) AssetDatabase.CreateFolder("Assets", "FaceTracking.Generated");
|
|||
|
var meshPath = pathToCurrentFolder + "/" + avatar.transform.name + ".mesh";
|
|||
|
AssetDatabase.CreateAsset(mesh, meshPath);
|
|||
|
|
|||
|
_faceTracking.FaceMesh.sharedMesh = mesh;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
mesh = _faceTracking.FaceMesh.sharedMesh;
|
|||
|
}
|
|||
|
|
|||
|
for (int i = 0; i < mesh.blendShapeCount; i++)
|
|||
|
{
|
|||
|
if (_faceTracking.FaceBlendShapes.Contains(mesh.GetBlendShapeName(i)))
|
|||
|
{
|
|||
|
var frameCount = mesh.GetBlendShapeFrameCount(i);
|
|||
|
var frameWeight = mesh.GetBlendShapeFrameWeight(i, frameCount - 1);
|
|||
|
if (!mesh.GetBlendShapeName(i).Contains("_overdrive"))
|
|||
|
{
|
|||
|
Vector3[] deltaVertices = new Vector3[mesh.vertexCount];
|
|||
|
Vector3[] deltaNormals = new Vector3[mesh.vertexCount];
|
|||
|
Vector3[] deltaTangents = new Vector3[mesh.vertexCount];
|
|||
|
mesh.GetBlendShapeFrameVertices(i, 0, deltaVertices, deltaNormals, deltaTangents);
|
|||
|
|
|||
|
for (int j=0; j < deltaVertices.Length; j++)
|
|||
|
{
|
|||
|
deltaVertices[j] = deltaVertices[j] * 5f;
|
|||
|
}
|
|||
|
|
|||
|
mesh.AddBlendShapeFrame(mesh.GetBlendShapeName(i)+"_overdrive", 100f, deltaVertices, deltaNormals, deltaTangents);
|
|||
|
var index = _faceTracking.FaceBlendShapes.ToList().FindIndex(m => m == mesh.GetBlendShapeName(i));
|
|||
|
_faceTracking.FaceBlendShapes[index] = mesh.GetBlendShapeName(i) + "_overdrive";
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
_faceTracking.GetBlendShapeNames();
|
|||
|
_faceTracking.enableOverdriveBlendShapes = true;
|
|||
|
|
|||
|
AssetDatabase.SaveAssets();
|
|||
|
}
|
|||
|
}
|
|||
|
}
|