// %BANNER_BEGIN% // --------------------------------------------------------------------- // %COPYRIGHT_BEGIN% // Copyright (c) 2023 Magic Leap, Inc. All Rights Reserved. // Use of this file is governed by the Software License Agreement, located here: https://www.magicleap.com/software-license-agreement-ml2 // Terms and conditions applicable to third-party materials accompanying this distribution may also be found in the top-level NOTICE file appearing herein. // %COPYRIGHT_END% // --------------------------------------------------------------------- // %BANNER_END% // Disabling deprecated warning for the internal project #pragma warning disable 618 using System; using System.Runtime.InteropServices; using UnityEngine.XR.MagicLeap.Native; namespace UnityEngine.XR.MagicLeap { public partial class MLFacialExpression : MLAutoAPISingleton { #region StructsAndEnums /// /// Available facial expressions. /// public enum EyeExpressionType { /// /// Blinking the left eye. /// BlinkLeft = 0, /// /// Blinking of the right eye. /// BlinkRight, /// /// Lower Lid upward movement of the left eye. /// LidTightenerLeft, /// /// Lower Lid upward movement of the right eye. /// LidTightenerRight, /// /// Upper lid upward movement of the left eye. /// EyeOpennessLeft, /// /// Upper lid upward movement of the right eye. /// EyeOpennessRight, /// /// Upward cheek movement, left. /// CheekRaiserLeft, /// /// Upward cheek movement, right. /// CheekRaiserRight, /// /// Downward brow movement, left. /// BrowLowererLeft, /// /// Downward brow movement, right. /// BrowLowererRight, /// /// Upward brow movement, left side. /// BrowRaiserLeft, /// /// Upward brow movement, right side. /// BrowRaiserRight } /// /// A structure containing settings for the facial expressions. /// public struct Settings { /// /// Enable MLFacialExpressionEyeData. If true, facial expressions will /// detect EyeData and the same can queried GetEyeData. This should be /// disabled when app does not need facial expression data /// public bool EnableEyeExpression; } /// /// A structure containing information about eye expressions. /// public struct EyeData { /// /// The MLTime timestamp when expression data was updated. /// public MLTime Timestamp; /// /// The values are between 0 and 1 and ordered such that the array should /// be indexed using EyeExpressionType. /// public float[] EyeExpressionWeights; } #endregion /// /// Start the API. /// protected override MLResult.Code StartAPI() => Instance.InternalMLFacialExpressionCreate(); /// /// Stop the API. /// protected override MLResult.Code StopAPI() => Instance.InternalMLFacialExpressionStop(); /// /// Updates Facial Expression system with new settings. /// /// public static MLResult.Code UpdateSettings(in Settings settings) => Instance.InternalUpdateSettings(settings); /// /// Get the latest eye data from the Facial Expression system. /// public static MLResult.Code GetEyeData(out EyeData data) => Instance.InternalGetEyeData(out data); #region InternalMethods /// /// Creates Facial Expression system client. /// private MLResult.Code InternalMLFacialExpressionCreate() { if (!MLResult.DidNativeCallSucceed(MLPermissions.CheckPermission(MLPermission.FacialExpression).Result)) { MLPluginLog.Error($"{nameof(MLFacialExpression)} requires missing permission {MLPermission.FacialExpression}"); return MLResult.Code.PermissionDenied; } NativeBindings.MLFacialExpressionSettings settings = NativeBindings.MLFacialExpressionSettings.Init(); MLResult.Code resultCode = NativeBindings.MLFacialExpressionCreateClient(ref settings, out Handle); MLResult.DidNativeCallSucceed(resultCode, nameof(NativeBindings.MLFacialExpressionCreateClient)); return resultCode; } /// /// Destroy Facial Expression system client. /// private MLResult.Code InternalMLFacialExpressionStop() { var resultCode = NativeBindings.MLFacialExpressionDestroyClient(Handle); MLResult.DidNativeCallSucceed(resultCode, nameof(NativeBindings.MLFacialExpressionDestroyClient)); return resultCode; } /// /// Updates API settings. /// private MLResult.Code InternalUpdateSettings(Settings settings) { NativeBindings.MLFacialExpressionSettings newSettings = NativeBindings.MLFacialExpressionSettings.Init(); newSettings.EnableEyeExpression = settings.EnableEyeExpression; var resultCode = NativeBindings.MLFacialExpressionUpdateSettings(Handle, newSettings); MLResult.DidNativeCallSucceed(resultCode, nameof(NativeBindings.MLFacialExpressionDestroyClient)); return resultCode; } /// /// Grabs eye data. /// /// private MLResult.Code InternalGetEyeData(out EyeData data) { data = new(); NativeBindings.MLFacialExpressionEyeData outData = NativeBindings.MLFacialExpressionEyeData.Init(); var resultCode = NativeBindings.MLFacialExpressionGetEyeData(Handle, out outData); if (MLResult.DidNativeCallSucceed(resultCode, nameof(NativeBindings.MLFacialExpressionGetEyeData))) { data.EyeExpressionWeights = outData.EyeExpressionWeights; data.Timestamp = outData.Timestamp; } return resultCode; } #endregion } }