Created
March 30, 2024 21:45
-
-
Save KevinRoussel/14ae70260cf459c6e643546ec4738347 to your computer and use it in GitHub Desktop.
FaceMapper_AutoSetup / Need UnityLiveCapture & NaughtyAttributes packages
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Reflection; | |
using NaughtyAttributes; | |
using Unity.LiveCapture.ARKitFaceCapture; | |
using Unity.LiveCapture.ARKitFaceCapture.DefaultMapper; | |
using UnityEngine; | |
public class FaceMapperAutoSetup : MonoBehaviour | |
{ | |
[SerializeField] DefaultFaceMapper _mapper; | |
[SerializeField] string SkinnedMeshNameGo = "head"; | |
IEnumerable<string> AllARFaces => Enum.GetNames(typeof(FaceBlendShape)).Except(new[] { "Invalid" }); | |
// Mesh data | |
SkinnedMeshRenderer Skin => (_mapper | |
.GetType() | |
.GetField("m_RigPrefab", BindingFlags.NonPublic | BindingFlags.Instance) | |
.GetValue(_mapper) as GameObject) | |
.transform | |
.Find(SkinnedMeshNameGo) | |
.GetComponent<SkinnedMeshRenderer>(); | |
// Face Data | |
object Maps => _mapper.GetType().GetPrivateField("m_Maps").GetValue(_mapper); // List<RendererMapping> | |
Array MapsEl => Maps.GetType().GetPrivateField("_items").GetValue(Maps) as Array; // Array[RendererMapping] | |
Array HeadBindings => MapsEl.GetValue(0) | |
.GetType() | |
.GetPrivateField("m_Bindings") | |
.GetValue(MapsEl.GetValue(0)) as Array; // Binding[] | |
IEnumerable<(object, FaceBlendShape, int)> GetBindings() | |
{ | |
for (int i = 0; i < HeadBindings.Length; i++) | |
{ | |
var el = HeadBindings.GetValue(i); // Binding | |
var type = el.GetType(); | |
FaceBlendShape face = (FaceBlendShape)(type.GetPrivateField("m_Location").GetValue(el)); | |
int faceIdx = (int)(type.GetPrivateField("m_ShapeIndex").GetValue(el)); | |
yield return (el, face, faceIdx); | |
} | |
} | |
void SetBinding(object binding, int value) => binding.GetType().GetPrivateField("m_ShapeIndex").SetValue(binding, value); | |
[Button] | |
void AutoSetup() | |
{ | |
var blendShape = Skin.sharedMesh.GetBlendShapeData(); | |
foreach (var el in GetBindings()) | |
{ | |
var txtlower = Enum.GetName(typeof(FaceBlendShape), el.Item2).ToLower(); | |
var rightBlendShapeIndex = blendShape.First(i => i.Item2 == txtlower).Item1; | |
SetBinding(el.Item1, rightBlendShapeIndex); | |
} | |
UnityEditor.EditorUtility.SetDirty(_mapper); | |
} | |
} | |
public static class MyExtension | |
{ | |
public static FieldInfo GetPrivateField(this Type @this, string n) | |
=> @this.GetField(n, BindingFlags.NonPublic | BindingFlags.Instance); | |
public static IEnumerable<(int, string)> GetBlendShapeData(this Mesh @this) | |
{ | |
(int, string)[] data = new (int, string)[@this.blendShapeCount]; | |
for (int i = 0; i < @this.blendShapeCount; i++) | |
{ | |
data[i] = (i, @this.GetBlendShapeName(i).ToLower()); | |
} | |
return data; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment