cvr-props/Assets/ABI.CCK/Scripts/Editor/CCK_CVRFaceTrackingEditor.cs

127 lines
6.2 KiB
C#
Raw Permalink Normal View History

2023-01-22 16:38:23 +01:00
using System.Collections.Generic;
using System.Linq;
using ABI.CCK.Components;
using ABI.CCK.Scripts.Editor;
2023-01-22 16:38:23 +01:00
using UnityEditor;
using UnityEngine;
namespace ABI.CCK.Scripts.Editor
{
[CustomEditor(typeof(CVRFaceTracking))]
2023-01-22 16:38:23 +01:00
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++)
{
_faceTracking.FaceBlendShapes[i] = EditorGUIExtensions.CustomPopup(
GUILayoutUtility.GetRect(new GUIContent(CVRFaceTracking.FaceBlendShapeNames[i]), EditorStyles.popup),
CVRFaceTracking.FaceBlendShapeNames[i],
_faceTracking.FaceBlendShapes[i],
_faceTracking.BlendShapeNames.ToArray(),
CVRFaceTracking.FaceBlendShapeNames[i]);
2023-01-22 16:38:23 +01:00
}
if (GUILayout.Button("Auto select Blendshapes"))
_faceTracking.AutoSelectFaceTrackingShapes();
2023-01-22 16:38:23 +01:00
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();
}
}
}