// Georgy Treshchev 2025. #include "BlendRealisticMetaHumanLipSyncAnimNode.h" #include "RuntimeMetaHumanLipSyncModule.h" #include "Animation/AnimInstanceProxy.h" #include "Misc/EngineVersionComparison.h" namespace RuntimeLipSync_GuiToRawControlsUtils { constexpr int32 NumGuiControls = 174; constexpr int32 NumRawControls = 251; using GuiControlsArray = TArray>; using RawControlsArray = TArray>; struct GuiToRawControlInfo { int32 InputIndex; // gui control int32 OutputIndex; // raw control float From; float To; float Slope; float Cut; }; const TSet EyesCurveNames = { "CTRL_expressions_eyeBlinkL", "CTRL_expressions_eyeBlinkR", "CTRL_expressions_eyeLidPressL", "CTRL_expressions_eyeLidPressR", "CTRL_expressions_eyeWidenL", "CTRL_expressions_eyeWidenR", "CTRL_expressions_eyeSquintInnerL", "CTRL_expressions_eyeSquintInnerR", "CTRL_expressions_eyeCheekRaiseL", "CTRL_expressions_eyeCheekRaiseR", "CTRL_expressions_eyeFaceScrunchL", "CTRL_expressions_eyeFaceScrunchR", "CTRL_expressions_eyeUpperLidUpL", "CTRL_expressions_eyeUpperLidUpR", "CTRL_expressions_eyeRelaxL", "CTRL_expressions_eyeRelaxR", "CTRL_expressions_eyeLowerLidUpL", "CTRL_expressions_eyeLowerLidUpR", "CTRL_expressions_eyeLowerLidDownL", "CTRL_expressions_eyeLowerLidDownR", "CTRL_expressions_eyeLookUpL", "CTRL_expressions_eyeLookUpR", "CTRL_expressions_eyeLookDownL", "CTRL_expressions_eyeLookDownR", "CTRL_expressions_eyeLookLeftL", "CTRL_expressions_eyeLookLeftR", "CTRL_expressions_eyeLookRightL", "CTRL_expressions_eyeLookRightR" }; const TArray DefaultGuiNames = { "CTRL_L_brow_down.ty", "CTRL_R_brow_down.ty", "CTRL_L_brow_lateral.ty", "CTRL_R_brow_lateral.ty", "CTRL_L_brow_raiseIn.ty", "CTRL_R_brow_raiseIn.ty", "CTRL_L_brow_raiseOut.ty", "CTRL_R_brow_raiseOut.ty", "CTRL_L_ear_up.ty", "CTRL_R_ear_up.ty", "CTRL_L_eye_blink.ty", "CTRL_R_eye_blink.ty", "CTRL_L_eye_lidPress.ty", "CTRL_R_eye_lidPress.ty", "CTRL_L_eye_squintInner.ty", "CTRL_R_eye_squintInner.ty", "CTRL_L_eye_cheekRaise.ty", "CTRL_R_eye_cheekRaise.ty", "CTRL_L_eye_faceScrunch.ty", "CTRL_R_eye_faceScrunch.ty", "CTRL_L_eye_eyelidU.ty", "CTRL_R_eye_eyelidU.ty", "CTRL_L_eye_eyelidD.ty", "CTRL_R_eye_eyelidD.ty", "CTRL_L_eye.ty", "CTRL_R_eye.ty", "CTRL_L_eye.tx", "CTRL_R_eye.tx", "CTRL_L_eye_pupil.ty", "CTRL_R_eye_pupil.ty", "CTRL_C_eye_parallelLook.ty", "CTRL_L_eyelashes_tweakerIn.ty", "CTRL_R_eyelashes_tweakerIn.ty", "CTRL_L_eyelashes_tweakerOut.ty", "CTRL_R_eyelashes_tweakerOut.ty", "CTRL_L_nose.ty", "CTRL_R_nose.ty", "CTRL_L_nose.tx", "CTRL_R_nose.tx", "CTRL_L_nose_wrinkleUpper.ty", "CTRL_R_nose_wrinkleUpper.ty", "CTRL_L_nose_nasolabialDeepen.ty", "CTRL_R_nose_nasolabialDeepen.ty", "CTRL_L_mouth_suckBlow.ty", "CTRL_R_mouth_suckBlow.ty", "CTRL_L_mouth_lipsBlow.ty", "CTRL_R_mouth_lipsBlow.ty", "CTRL_C_mouth.ty", "CTRL_C_mouth.tx", "CTRL_L_mouth_upperLipRaise.ty", "CTRL_R_mouth_upperLipRaise.ty", "CTRL_L_mouth_lowerLipDepress.ty", "CTRL_R_mouth_lowerLipDepress.ty", "CTRL_L_mouth_cornerPull.ty", "CTRL_R_mouth_cornerPull.ty", "CTRL_L_mouth_stretch.ty", "CTRL_R_mouth_stretch.ty", "CTRL_L_mouth_stretchLipsClose.ty", "CTRL_R_mouth_stretchLipsClose.ty", "CTRL_L_mouth_dimple.ty", "CTRL_R_mouth_dimple.ty", "CTRL_L_mouth_cornerDepress.ty", "CTRL_R_mouth_cornerDepress.ty", "CTRL_L_mouth_pressU.ty", "CTRL_R_mouth_pressU.ty", "CTRL_L_mouth_pressD.ty", "CTRL_R_mouth_pressD.ty", "CTRL_L_mouth_purseU.ty", "CTRL_R_mouth_purseU.ty", "CTRL_L_mouth_purseD.ty", "CTRL_R_mouth_purseD.ty", "CTRL_L_mouth_towardsU.ty", "CTRL_R_mouth_towardsU.ty", "CTRL_L_mouth_towardsD.ty", "CTRL_R_mouth_towardsD.ty", "CTRL_L_mouth_funnelU.ty", "CTRL_R_mouth_funnelU.ty", "CTRL_L_mouth_funnelD.ty", "CTRL_R_mouth_funnelD.ty", "CTRL_L_mouth_lipsTogetherU.ty", "CTRL_R_mouth_lipsTogetherU.ty", "CTRL_L_mouth_lipsTogetherD.ty", "CTRL_R_mouth_lipsTogetherD.ty", "CTRL_L_mouth_lipBiteU.ty", "CTRL_R_mouth_lipBiteU.ty", "CTRL_L_mouth_lipBiteD.ty", "CTRL_R_mouth_lipBiteD.ty", "CTRL_L_mouth_tightenU.ty", "CTRL_R_mouth_tightenU.ty", "CTRL_L_mouth_tightenD.ty", "CTRL_R_mouth_tightenD.ty", "CTRL_L_mouth_lipsPressU.ty", "CTRL_R_mouth_lipsPressU.ty", "CTRL_L_mouth_sharpCornerPull.ty", "CTRL_R_mouth_sharpCornerPull.ty", "CTRL_C_mouth_stickyU.ty", "CTRL_L_mouth_stickyInnerU.ty", "CTRL_R_mouth_stickyInnerU.ty", "CTRL_L_mouth_stickyOuterU.ty", "CTRL_R_mouth_stickyOuterU.ty", "CTRL_C_mouth_stickyD.ty", "CTRL_L_mouth_stickyInnerD.ty", "CTRL_R_mouth_stickyInnerD.ty", "CTRL_L_mouth_stickyOuterD.ty", "CTRL_R_mouth_stickyOuterD.ty", "CTRL_L_mouth_lipSticky.ty", "CTRL_R_mouth_lipSticky.ty", "CTRL_L_mouth_pushPullU.ty", "CTRL_R_mouth_pushPullU.ty", "CTRL_L_mouth_pushPullD.ty", "CTRL_R_mouth_pushPullD.ty", "CTRL_L_mouth_thicknessU.ty", "CTRL_R_mouth_thicknessU.ty", "CTRL_L_mouth_thicknessD.ty", "CTRL_R_mouth_thicknessD.ty", "CTRL_L_mouth_thicknessInwardU.ty", "CTRL_R_mouth_thicknessInwardU.ty", "CTRL_L_mouth_thicknessInwardD.ty", "CTRL_R_mouth_thicknessInwardD.ty", "CTRL_L_mouth_cornerSharpnessU.ty", "CTRL_R_mouth_cornerSharpnessU.ty", "CTRL_L_mouth_cornerSharpnessD.ty", "CTRL_R_mouth_cornerSharpnessD.ty", "CTRL_L_mouth_lipsTowardsTeethU.ty", "CTRL_R_mouth_lipsTowardsTeethU.ty", "CTRL_L_mouth_lipsTowardsTeethD.ty", "CTRL_R_mouth_lipsTowardsTeethD.ty", "CTRL_C_mouth_lipShiftU.ty", "CTRL_C_mouth_lipShiftD.ty", "CTRL_L_mouth_lipsRollU.ty", "CTRL_R_mouth_lipsRollU.ty", "CTRL_L_mouth_lipsRollD.ty", "CTRL_R_mouth_lipsRollD.ty", "CTRL_L_mouth_corner.ty", "CTRL_L_mouth_corner.tx", "CTRL_R_mouth_corner.ty", "CTRL_R_mouth_corner.tx", "CTRL_C_tongue_inOut.ty", "CTRL_C_tongue_move.ty", "CTRL_C_tongue_move.tx", "CTRL_C_tongue_press.ty", "CTRL_C_tongue_wideNarrow.ty", "CTRL_C_tongue_bendTwist.ty", "CTRL_C_tongue_bendTwist.tx", "CTRL_C_tongue_roll.ty", "CTRL_C_tongue_tipMove.ty", "CTRL_C_tongue_tipMove.tx", "CTRL_C_tongue_thickThin.ty", "CTRL_C_jaw.ty", "CTRL_C_jaw.tx", "CTRL_C_jaw_fwdBack.ty", "CTRL_L_jaw_clench.ty", "CTRL_R_jaw_clench.ty", "CTRL_L_jaw_ChinRaiseU.ty", "CTRL_R_jaw_ChinRaiseU.ty", "CTRL_L_jaw_ChinRaiseD.ty", "CTRL_R_jaw_ChinRaiseD.ty", "CTRL_L_jaw_chinCompress.ty", "CTRL_R_jaw_chinCompress.ty", "CTRL_C_jaw_openExtreme.ty", "CTRL_L_neck_stretch.ty", "CTRL_R_neck_stretch.ty", "CTRL_C_neck_swallow.ty", "CTRL_L_neck_mastoidContract.ty", "CTRL_R_neck_mastoidContract.ty", "CTRL_neck_throatUpDown.ty", "CTRL_neck_digastricUpDown.ty", "CTRL_neck_throatExhaleInhale.ty", "CTRL_C_teethU.ty", "CTRL_C_teethU.tx", "CTRL_C_teeth_fwdBackU.ty", "CTRL_C_teethD.ty", "CTRL_C_teethD.tx", "CTRL_C_teeth_fwdBackD.ty", }; const TArray DefaultRawControlNames = { "CTRL_expressions_browDownL", "CTRL_expressions_browDownR", "CTRL_expressions_browLateralL", "CTRL_expressions_browLateralR", "CTRL_expressions_browRaiseInL", "CTRL_expressions_browRaiseInR", "CTRL_expressions_browRaiseOuterL", "CTRL_expressions_browRaiseOuterR", "CTRL_expressions_earUpL", "CTRL_expressions_earUpR", "CTRL_expressions_eyeBlinkL", "CTRL_expressions_eyeBlinkR", "CTRL_expressions_eyeLidPressL", "CTRL_expressions_eyeLidPressR", "CTRL_expressions_eyeWidenL", "CTRL_expressions_eyeWidenR", "CTRL_expressions_eyeSquintInnerL", "CTRL_expressions_eyeSquintInnerR", "CTRL_expressions_eyeCheekRaiseL", "CTRL_expressions_eyeCheekRaiseR", "CTRL_expressions_eyeFaceScrunchL", "CTRL_expressions_eyeFaceScrunchR", "CTRL_expressions_eyeUpperLidUpL", "CTRL_expressions_eyeUpperLidUpR", "CTRL_expressions_eyeRelaxL", "CTRL_expressions_eyeRelaxR", "CTRL_expressions_eyeLowerLidUpL", "CTRL_expressions_eyeLowerLidUpR", "CTRL_expressions_eyeLowerLidDownL", "CTRL_expressions_eyeLowerLidDownR", "CTRL_expressions_eyeLookUpL", "CTRL_expressions_eyeLookUpR", "CTRL_expressions_eyeLookDownL", "CTRL_expressions_eyeLookDownR", "CTRL_expressions_eyeLookLeftL", "CTRL_expressions_eyeLookLeftR", "CTRL_expressions_eyeLookRightL", "CTRL_expressions_eyeLookRightR", "CTRL_expressions_eyePupilWideL", "CTRL_expressions_eyePupilWideR", "CTRL_expressions_eyePupilNarrowL", "CTRL_expressions_eyePupilNarrowR", "CTRL_expressions_eyeParallelLookDirection", "CTRL_expressions_eyelashesUpINL", "CTRL_expressions_eyelashesUpINR", "CTRL_expressions_eyelashesUpOUTL", "CTRL_expressions_eyelashesUpOUTR", "CTRL_expressions_eyelashesDownINL", "CTRL_expressions_eyelashesDownINR", "CTRL_expressions_eyelashesDownOUTL", "CTRL_expressions_eyelashesDownOUTR", "CTRL_expressions_noseWrinkleL", "CTRL_expressions_noseWrinkleR", "CTRL_expressions_noseWrinkleUpperL", "CTRL_expressions_noseWrinkleUpperR", "CTRL_expressions_noseNostrilDepressL", "CTRL_expressions_noseNostrilDepressR", "CTRL_expressions_noseNostrilDilateL", "CTRL_expressions_noseNostrilDilateR", "CTRL_expressions_noseNostrilCompressL", "CTRL_expressions_noseNostrilCompressR", "CTRL_expressions_noseNasolabialDeepenL", "CTRL_expressions_noseNasolabialDeepenR", "CTRL_expressions_mouthCheekSuckL", "CTRL_expressions_mouthCheekSuckR", "CTRL_expressions_mouthCheekBlowL", "CTRL_expressions_mouthCheekBlowR", "CTRL_expressions_mouthLipsBlowL", "CTRL_expressions_mouthLipsBlowR", "CTRL_expressions_mouthLeft", "CTRL_expressions_mouthRight", "CTRL_expressions_mouthUp", "CTRL_expressions_mouthDown", "CTRL_expressions_mouthUpperLipRaiseL", "CTRL_expressions_mouthUpperLipRaiseR", "CTRL_expressions_mouthLowerLipDepressL", "CTRL_expressions_mouthLowerLipDepressR", "CTRL_expressions_mouthCornerPullL", "CTRL_expressions_mouthCornerPullR", "CTRL_expressions_mouthStretchL", "CTRL_expressions_mouthStretchR", "CTRL_expressions_mouthStretchLipsCloseL", "CTRL_expressions_mouthStretchLipsCloseR", "CTRL_expressions_mouthDimpleL", "CTRL_expressions_mouthDimpleR", "CTRL_expressions_mouthCornerDepressL", "CTRL_expressions_mouthCornerDepressR", "CTRL_expressions_mouthPressUL", "CTRL_expressions_mouthPressUR", "CTRL_expressions_mouthPressDL", "CTRL_expressions_mouthPressDR", "CTRL_expressions_mouthLipsPurseUL", "CTRL_expressions_mouthLipsPurseUR", "CTRL_expressions_mouthLipsPurseDL", "CTRL_expressions_mouthLipsPurseDR", "CTRL_expressions_mouthLipsTowardsUL", "CTRL_expressions_mouthLipsTowardsUR", "CTRL_expressions_mouthLipsTowardsDL", "CTRL_expressions_mouthLipsTowardsDR", "CTRL_expressions_mouthFunnelUL", "CTRL_expressions_mouthFunnelUR", "CTRL_expressions_mouthFunnelDL", "CTRL_expressions_mouthFunnelDR", "CTRL_expressions_mouthLipsTogetherUL", "CTRL_expressions_mouthLipsTogetherUR", "CTRL_expressions_mouthLipsTogetherDL", "CTRL_expressions_mouthLipsTogetherDR", "CTRL_expressions_mouthUpperLipBiteL", "CTRL_expressions_mouthUpperLipBiteR", "CTRL_expressions_mouthLowerLipBiteL", "CTRL_expressions_mouthLowerLipBiteR", "CTRL_expressions_mouthLipsTightenUL", "CTRL_expressions_mouthLipsTightenUR", "CTRL_expressions_mouthLipsTightenDL", "CTRL_expressions_mouthLipsTightenDR", "CTRL_expressions_mouthLipsPressL", "CTRL_expressions_mouthLipsPressR", "CTRL_expressions_mouthSharpCornerPullL", "CTRL_expressions_mouthSharpCornerPullR", "CTRL_expressions_mouthStickyUC", "CTRL_expressions_mouthStickyUINL", "CTRL_expressions_mouthStickyUINR", "CTRL_expressions_mouthStickyUOUTL", "CTRL_expressions_mouthStickyUOUTR", "CTRL_expressions_mouthStickyDC", "CTRL_expressions_mouthStickyDINL", "CTRL_expressions_mouthStickyDINR", "CTRL_expressions_mouthStickyDOUTL", "CTRL_expressions_mouthStickyDOUTR", "CTRL_expressions_mouthLipsStickyLPh1", "CTRL_expressions_mouthLipsStickyLPh2", "CTRL_expressions_mouthLipsStickyLPh3", "CTRL_expressions_mouthLipsStickyRPh1", "CTRL_expressions_mouthLipsStickyRPh2", "CTRL_expressions_mouthLipsStickyRPh3", "CTRL_expressions_mouthLipsPushUL", "CTRL_expressions_mouthLipsPushUR", "CTRL_expressions_mouthLipsPushDL", "CTRL_expressions_mouthLipsPushDR", "CTRL_expressions_mouthLipsPullUL", "CTRL_expressions_mouthLipsPullUR", "CTRL_expressions_mouthLipsPullDL", "CTRL_expressions_mouthLipsPullDR", "CTRL_expressions_mouthLipsThinUL", "CTRL_expressions_mouthLipsThinUR", "CTRL_expressions_mouthLipsThinDL", "CTRL_expressions_mouthLipsThinDR", "CTRL_expressions_mouthLipsThickUL", "CTRL_expressions_mouthLipsThickUR", "CTRL_expressions_mouthLipsThickDL", "CTRL_expressions_mouthLipsThickDR", "CTRL_expressions_mouthLipsThinInwardUL", "CTRL_expressions_mouthLipsThinInwardUR", "CTRL_expressions_mouthLipsThinInwardDL", "CTRL_expressions_mouthLipsThinInwardDR", "CTRL_expressions_mouthLipsThickInwardUL", "CTRL_expressions_mouthLipsThickInwardUR", "CTRL_expressions_mouthLipsThickInwardDL", "CTRL_expressions_mouthLipsThickInwardDR", "CTRL_expressions_mouthCornerSharpenUL", "CTRL_expressions_mouthCornerSharpenUR", "CTRL_expressions_mouthCornerSharpenDL", "CTRL_expressions_mouthCornerSharpenDR", "CTRL_expressions_mouthCornerRounderUL", "CTRL_expressions_mouthCornerRounderUR", "CTRL_expressions_mouthCornerRounderDL", "CTRL_expressions_mouthCornerRounderDR", "CTRL_expressions_mouthUpperLipTowardsTeethL", "CTRL_expressions_mouthUpperLipTowardsTeethR", "CTRL_expressions_mouthLowerLipTowardsTeethL", "CTRL_expressions_mouthLowerLipTowardsTeethR", "CTRL_expressions_mouthUpperLipShiftLeft", "CTRL_expressions_mouthUpperLipShiftRight", "CTRL_expressions_mouthLowerLipShiftLeft", "CTRL_expressions_mouthLowerLipShiftRight", "CTRL_expressions_mouthUpperLipRollInL", "CTRL_expressions_mouthUpperLipRollInR", "CTRL_expressions_mouthUpperLipRollOutL", "CTRL_expressions_mouthUpperLipRollOutR", "CTRL_expressions_mouthLowerLipRollInL", "CTRL_expressions_mouthLowerLipRollInR", "CTRL_expressions_mouthLowerLipRollOutL", "CTRL_expressions_mouthLowerLipRollOutR", "CTRL_expressions_mouthCornerUpL", "CTRL_expressions_mouthCornerUpR", "CTRL_expressions_mouthCornerDownL", "CTRL_expressions_mouthCornerDownR", "CTRL_expressions_mouthCornerWideL", "CTRL_expressions_mouthCornerWideR", "CTRL_expressions_mouthCornerNarrowL", "CTRL_expressions_mouthCornerNarrowR", "CTRL_expressions_jawOpen", "CTRL_expressions_jawLeft", "CTRL_expressions_jawRight", "CTRL_expressions_jawFwd", "CTRL_expressions_jawBack", "CTRL_expressions_jawClenchL", "CTRL_expressions_jawClenchR", "CTRL_expressions_jawChinRaiseDL", "CTRL_expressions_jawChinRaiseDR", "CTRL_expressions_jawChinRaiseUL", "CTRL_expressions_jawChinRaiseUR", "CTRL_expressions_jawChinCompressL", "CTRL_expressions_jawChinCompressR", "CTRL_expressions_jawOpenExtreme", "CTRL_expressions_neckStretchL", "CTRL_expressions_neckStretchR", "CTRL_expressions_neckSwallowPh1", "CTRL_expressions_neckSwallowPh2", "CTRL_expressions_neckSwallowPh3", "CTRL_expressions_neckSwallowPh4", "CTRL_expressions_neckMastoidContractL", "CTRL_expressions_neckMastoidContractR", "CTRL_expressions_neckThroatDown", "CTRL_expressions_neckThroatUp", "CTRL_expressions_neckDigastricDown", "CTRL_expressions_neckDigastricUp", "CTRL_expressions_neckThroatExhale", "CTRL_expressions_neckThroatInhale", "CTRL_expressions_teethUpU", "CTRL_expressions_teethUpD", "CTRL_expressions_teethDownU", "CTRL_expressions_teethDownD", "CTRL_expressions_teethLeftU", "CTRL_expressions_teethLeftD", "CTRL_expressions_teethRightU", "CTRL_expressions_teethRightD", "CTRL_expressions_teethFwdU", "CTRL_expressions_teethFwdD", "CTRL_expressions_teethBackU", "CTRL_expressions_teethBackD", "CTRL_expressions_tongueUp", "CTRL_expressions_tongueDown", "CTRL_expressions_tongueLeft", "CTRL_expressions_tongueRight", "CTRL_expressions_tongueOut", "CTRL_expressions_tongueIn", "CTRL_expressions_tongueBendUp", "CTRL_expressions_tongueBendDown", "CTRL_expressions_tongueTwistLeft", "CTRL_expressions_tongueTwistRight", "CTRL_expressions_tongueTipUp", "CTRL_expressions_tongueTipDown", "CTRL_expressions_tongueTipLeft", "CTRL_expressions_tongueTipRight", "CTRL_expressions_tongueWide", "CTRL_expressions_tongueNarrow", "CTRL_expressions_tonguePress", "CTRL_expressions_tongueRoll", "CTRL_expressions_tongueThick", "CTRL_expressions_tongueThin" }; const TArray GuiToRawMappings = { {0, 0, 0.000000, 1.000000, 1.000000, 0.000000}, {1, 1, 0.000000, 1.000000, 1.000000, 0.000000}, {2, 2, 0.000000, 1.000000, 1.000000, 0.000000}, {3, 3, 0.000000, 1.000000, 1.000000, 0.000000}, {4, 4, 0.000000, 1.000000, 1.000000, 0.000000}, {5, 5, 0.000000, 1.000000, 1.000000, 0.000000}, {6, 6, 0.000000, 1.000000, 1.000000, 0.000000}, {7, 7, 0.000000, 1.000000, 1.000000, 0.000000}, {8, 8, 0.000000, 1.000000, 1.000000, 0.000000}, {9, 9, 0.000000, 1.000000, 1.000000, 0.000000}, {10, 10, 0.000000, 1.000000, 1.000000, 0.000000}, {11, 11, 0.000000, 1.000000, 1.000000, 0.000000}, {10, 14, -1.000000, 0.000000, -1.000000, 0.000000}, {11, 15, -1.000000, 0.000000, -1.000000, 0.000000}, {12, 12, 0.000000, 1.000000, 1.000000, 0.000000}, {13, 13, 0.000000, 1.000000, 1.000000, 0.000000}, {14, 16, 0.000000, 1.000000, 1.000000, 0.000000}, {15, 17, 0.000000, 1.000000, 1.000000, 0.000000}, {16, 18, 0.000000, 1.000000, 1.000000, 0.000000}, {17, 19, 0.000000, 1.000000, 1.000000, 0.000000}, {18, 20, 0.000000, 1.000000, 1.000000, 0.000000}, {19, 21, 0.000000, 1.000000, 1.000000, 0.000000}, {20, 22, -1.000000, 0.000000, -1.000000, 0.000000}, {21, 23, -1.000000, 0.000000, -1.000000, 0.000000}, {20, 24, 0.000000, 1.000000, 1.000000, 0.000000}, {21, 25, 0.000000, 1.000000, 1.000000, 0.000000}, {22, 28, -1.000000, 0.000000, -1.000000, 0.000000}, {23, 29, -1.000000, 0.000000, -1.000000, 0.000000}, {22, 26, 0.000000, 1.000000, 1.000000, 0.000000}, {23, 27, 0.000000, 1.000000, 1.000000, 0.000000}, {24, 30, 0.000000, 1.000000, 1.000000, 0.000000}, {25, 31, 0.000000, 1.000000, 1.000000, 0.000000}, {24, 32, -1.000000, 0.000000, -1.000000, 0.000000}, {25, 33, -1.000000, 0.000000, -1.000000, 0.000000}, {26, 34, 0.000000, 1.000000, 1.000000, 0.000000}, {27, 35, 0.000000, 1.000000, 1.000000, 0.000000}, {26, 36, -1.000000, 0.000000, -1.000000, 0.000000}, {27, 37, -1.000000, 0.000000, -1.000000, 0.000000}, {28, 38, 0.000000, 1.000000, 1.000000, 0.000000}, {29, 39, 0.000000, 1.000000, 1.000000, 0.000000}, {28, 40, -1.000000, 0.000000, -1.000000, 0.000000}, {29, 41, -1.000000, 0.000000, -1.000000, 0.000000}, {30, 42, 0.000000, 1.000000, 1.000000, 0.000000}, {31, 47, 0.000000, 1.000000, 1.000000, 0.000000}, {32, 48, 0.000000, 1.000000, 1.000000, 0.000000}, {33, 49, 0.000000, 1.000000, 1.000000, 0.000000}, {34, 50, 0.000000, 1.000000, 1.000000, 0.000000}, {31, 43, -1.000000, 0.000000, -1.000000, 0.000000}, {32, 44, -1.000000, 0.000000, -1.000000, 0.000000}, {33, 45, -1.000000, 0.000000, -1.000000, 0.000000}, {34, 46, -1.000000, 0.000000, -1.000000, 0.000000}, {35, 51, 0.000000, 1.000000, 1.000000, 0.000000}, {36, 52, 0.000000, 1.000000, 1.000000, 0.000000}, {35, 55, -1.000000, 0.000000, -1.000000, 0.000000}, {36, 56, -1.000000, 0.000000, -1.000000, 0.000000}, {37, 57, 0.000000, 1.000000, 1.000000, 0.000000}, {38, 58, 0.000000, 1.000000, 1.000000, 0.000000}, {37, 59, -1.000000, 0.000000, -1.000000, 0.000000}, {38, 60, -1.000000, 0.000000, -1.000000, 0.000000}, {39, 53, 0.000000, 1.000000, 1.000000, 0.000000}, {40, 54, 0.000000, 1.000000, 1.000000, 0.000000}, {41, 61, 0.000000, 1.000000, 1.000000, 0.000000}, {42, 62, 0.000000, 1.000000, 1.000000, 0.000000}, {43, 65, 0.000000, 1.000000, 1.000000, 0.000000}, {44, 66, 0.000000, 1.000000, 1.000000, 0.000000}, {43, 63, -1.000000, 0.000000, -1.000000, 0.000000}, {44, 64, -1.000000, 0.000000, -1.000000, 0.000000}, {45, 67, 0.000000, 1.000000, 1.000000, 0.000000}, {46, 68, 0.000000, 1.000000, 1.000000, 0.000000}, {47, 71, 0.000000, 1.000000, 1.000000, 0.000000}, {47, 72, -1.000000, 0.000000, -1.000000, 0.000000}, {48, 69, 0.000000, 1.000000, 1.000000, 0.000000}, {48, 70, -1.000000, 0.000000, -1.000000, 0.000000}, {49, 73, 0.000000, 1.000000, 1.000000, 0.000000}, {50, 74, 0.000000, 1.000000, 1.000000, 0.000000}, {51, 75, 0.000000, 1.000000, 1.000000, 0.000000}, {52, 76, 0.000000, 1.000000, 1.000000, 0.000000}, {53, 77, 0.000000, 1.000000, 1.000000, 0.000000}, {54, 78, 0.000000, 1.000000, 1.000000, 0.000000}, {55, 79, 0.000000, 1.000000, 1.000000, 0.000000}, {56, 80, 0.000000, 1.000000, 1.000000, 0.000000}, {57, 81, 0.000000, 1.000000, 1.000000, 0.000000}, {58, 82, 0.000000, 1.000000, 1.000000, 0.000000}, {59, 83, 0.000000, 1.000000, 1.000000, 0.000000}, {60, 84, 0.000000, 1.000000, 1.000000, 0.000000}, {61, 85, 0.000000, 1.000000, 1.000000, 0.000000}, {62, 86, 0.000000, 1.000000, 1.000000, 0.000000}, {63, 87, 0.000000, 1.000000, 1.000000, 0.000000}, {64, 88, 0.000000, 1.000000, 1.000000, 0.000000}, {65, 89, 0.000000, 1.000000, 1.000000, 0.000000}, {66, 90, 0.000000, 1.000000, 1.000000, 0.000000}, {67, 91, 0.000000, 1.000000, 1.000000, 0.000000}, {68, 92, 0.000000, 1.000000, 1.000000, 0.000000}, {69, 93, 0.000000, 1.000000, 1.000000, 0.000000}, {70, 94, 0.000000, 1.000000, 1.000000, 0.000000}, {71, 95, 0.000000, 1.000000, 1.000000, 0.000000}, {72, 96, 0.000000, 1.000000, 1.000000, 0.000000}, {73, 97, 0.000000, 1.000000, 1.000000, 0.000000}, {74, 98, 0.000000, 1.000000, 1.000000, 0.000000}, {75, 99, 0.000000, 1.000000, 1.000000, 0.000000}, {76, 100, 0.000000, 1.000000, 1.000000, 0.000000}, {77, 101, 0.000000, 1.000000, 1.000000, 0.000000}, {78, 102, 0.000000, 1.000000, 1.000000, 0.000000}, {79, 103, 0.000000, 1.000000, 1.000000, 0.000000}, {80, 104, 0.000000, 1.000000, 1.000000, 0.000000}, {81, 105, 0.000000, 1.000000, 1.000000, 0.000000}, {82, 106, 0.000000, 1.000000, 1.000000, 0.000000}, {83, 107, 0.000000, 1.000000, 1.000000, 0.000000}, {84, 108, 0.000000, 1.000000, 1.000000, 0.000000}, {85, 109, 0.000000, 1.000000, 1.000000, 0.000000}, {86, 110, 0.000000, 1.000000, 1.000000, 0.000000}, {87, 111, 0.000000, 1.000000, 1.000000, 0.000000}, {88, 112, 0.000000, 1.000000, 1.000000, 0.000000}, {89, 113, 0.000000, 1.000000, 1.000000, 0.000000}, {90, 114, 0.000000, 1.000000, 1.000000, 0.000000}, {91, 115, 0.000000, 1.000000, 1.000000, 0.000000}, {92, 116, 0.000000, 1.000000, 1.000000, 0.000000}, {93, 117, 0.000000, 1.000000, 1.000000, 0.000000}, {94, 118, 0.000000, 1.000000, 1.000000, 0.000000}, {95, 119, 0.000000, 1.000000, 1.000000, 0.000000}, {96, 120, 0.000000, 1.000000, 1.000000, 0.000000}, {97, 121, 0.000000, 1.000000, 1.000000, 0.000000}, {98, 122, 0.000000, 1.000000, 1.000000, 0.000000}, {99, 123, 0.000000, 1.000000, 1.000000, 0.000000}, {100, 124, 0.000000, 1.000000, 1.000000, 0.000000}, {101, 125, 0.000000, 1.000000, 1.000000, 0.000000}, {102, 126, 0.000000, 1.000000, 1.000000, 0.000000}, {103, 127, 0.000000, 1.000000, 1.000000, 0.000000}, {104, 128, 0.000000, 1.000000, 1.000000, 0.000000}, {105, 129, 0.000000, 0.330000, 3.030303, 0.000000}, {105, 129, 0.330000, 0.660000, -3.030303, 2.000000}, {105, 130, 0.330000, 0.660000, 3.030303, -1.000000}, {105, 130, 0.660000, 1.000000, -2.941176, 2.941176}, {105, 131, 0.660000, 1.000000, 2.941176, -1.941176}, {106, 132, 0.000000, 0.330000, 3.030303, 0.000000}, {106, 132, 0.330000, 0.660000, -3.030303, 2.000000}, {106, 133, 0.330000, 0.660000, 3.030303, -1.000000}, {106, 133, 0.660000, 1.000000, -2.941176, 2.941176}, {106, 134, 0.660000, 1.000000, 2.941176, -1.941176}, {107, 135, 0.000000, 1.000000, 1.000000, 0.000000}, {108, 136, 0.000000, 1.000000, 1.000000, 0.000000}, {109, 137, 0.000000, 1.000000, 1.000000, 0.000000}, {110, 138, 0.000000, 1.000000, 1.000000, 0.000000}, {107, 139, -1.000000, 0.000000, -1.000000, 0.000000}, {108, 140, -1.000000, 0.000000, -1.000000, 0.000000}, {109, 141, -1.000000, 0.000000, -1.000000, 0.000000}, {110, 142, -1.000000, 0.000000, -1.000000, 0.000000}, {111, 143, 0.000000, 1.000000, 1.000000, 0.000000}, {112, 144, 0.000000, 1.000000, 1.000000, 0.000000}, {113, 145, 0.000000, 1.000000, 1.000000, 0.000000}, {114, 146, 0.000000, 1.000000, 1.000000, 0.000000}, {111, 147, -1.000000, 0.000000, -1.000000, 0.000000}, {112, 148, -1.000000, 0.000000, -1.000000, 0.000000}, {113, 149, -1.000000, 0.000000, -1.000000, 0.000000}, {114, 150, -1.000000, 0.000000, -1.000000, 0.000000}, {115, 151, 0.000000, 1.000000, 1.000000, 0.000000}, {116, 152, 0.000000, 1.000000, 1.000000, 0.000000}, {117, 153, 0.000000, 1.000000, 1.000000, 0.000000}, {118, 154, 0.000000, 1.000000, 1.000000, 0.000000}, {115, 155, -1.000000, 0.000000, -1.000000, 0.000000}, {116, 156, -1.000000, 0.000000, -1.000000, 0.000000}, {117, 157, -1.000000, 0.000000, -1.000000, 0.000000}, {118, 158, -1.000000, 0.000000, -1.000000, 0.000000}, {119, 159, 0.000000, 1.000000, 1.000000, 0.000000}, {120, 160, 0.000000, 1.000000, 1.000000, 0.000000}, {121, 161, 0.000000, 1.000000, 1.000000, 0.000000}, {122, 162, 0.000000, 1.000000, 1.000000, 0.000000}, {119, 163, -1.000000, 0.000000, -1.000000, 0.000000}, {120, 164, -1.000000, 0.000000, -1.000000, 0.000000}, {121, 165, -1.000000, 0.000000, -1.000000, 0.000000}, {122, 166, -1.000000, 0.000000, -1.000000, 0.000000}, {123, 167, 0.000000, 1.000000, 1.000000, 0.000000}, {124, 168, 0.000000, 1.000000, 1.000000, 0.000000}, {125, 169, 0.000000, 1.000000, 1.000000, 0.000000}, {126, 170, 0.000000, 1.000000, 1.000000, 0.000000}, {127, 171, 0.000000, 1.000000, 1.000000, 0.000000}, {127, 172, -1.000000, 0.000000, -1.000000, 0.000000}, {128, 173, 0.000000, 1.000000, 1.000000, 0.000000}, {128, 174, -1.000000, 0.000000, -1.000000, 0.000000}, {129, 175, 0.000000, 1.000000, 1.000000, 0.000000}, {130, 176, 0.000000, 1.000000, 1.000000, 0.000000}, {131, 179, 0.000000, 1.000000, 1.000000, 0.000000}, {132, 180, 0.000000, 1.000000, 1.000000, 0.000000}, {129, 177, -1.000000, 0.000000, -1.000000, 0.000000}, {130, 178, -1.000000, 0.000000, -1.000000, 0.000000}, {131, 181, -1.000000, 0.000000, -1.000000, 0.000000}, {132, 182, -1.000000, 0.000000, -1.000000, 0.000000}, {133, 183, 0.000000, 1.000000, 1.000000, 0.000000}, {133, 185, -1.000000, 0.000000, -1.000000, 0.000000}, {134, 187, 0.000000, 1.000000, 1.000000, 0.000000}, {134, 189, -1.000000, 0.000000, -1.000000, 0.000000}, {135, 184, 0.000000, 1.000000, 1.000000, 0.000000}, {135, 186, -1.000000, 0.000000, -1.000000, 0.000000}, {136, 188, 0.000000, 1.000000, 1.000000, 0.000000}, {136, 190, -1.000000, 0.000000, -1.000000, 0.000000}, {137, 236, 0.000000, 1.000000, 1.000000, 0.000000}, {137, 235, -1.000000, 0.000000, -1.000000, 0.000000}, {138, 231, 0.000000, 1.000000, 1.000000, 0.000000}, {138, 232, -1.000000, 0.000000, -1.000000, 0.000000}, {139, 233, 0.000000, 1.000000, 1.000000, 0.000000}, {139, 234, -1.000000, 0.000000, -1.000000, 0.000000}, {140, 247, 0.000000, 1.000000, 1.000000, 0.000000}, {141, 245, 0.000000, 1.000000, 1.000000, 0.000000}, {141, 246, -1.000000, 0.000000, -1.000000, 0.000000}, {142, 237, 0.000000, 1.000000, 1.000000, 0.000000}, {142, 238, -1.000000, 0.000000, -1.000000, 0.000000}, {143, 239, 0.000000, 1.000000, 1.000000, 0.000000}, {143, 240, -1.000000, 0.000000, -1.000000, 0.000000}, {144, 248, 0.000000, 1.000000, 1.000000, 0.000000}, {145, 241, 0.000000, 1.000000, 1.000000, 0.000000}, {145, 242, -1.000000, 0.000000, -1.000000, 0.000000}, {146, 243, 0.000000, 1.000000, 1.000000, 0.000000}, {146, 244, -1.000000, 0.000000, -1.000000, 0.000000}, {147, 249, 0.000000, 1.000000, 1.000000, 0.000000}, {147, 250, -1.000000, 0.000000, -1.000000, 0.000000}, {148, 191, 0.000000, 1.000000, 1.000000, 0.000000}, {149, 192, -1.000000, 0.000000, -1.000000, 0.000000}, {149, 193, 0.000000, 1.000000, 1.000000, 0.000000}, {150, 194, -1.000000, 0.000000, -1.000000, 0.000000}, {150, 195, 0.000000, 1.000000, 1.000000, 0.000000}, {151, 196, 0.000000, 1.000000, 1.000000, 0.000000}, {152, 197, 0.000000, 1.000000, 1.000000, 0.000000}, {153, 200, 0.000000, 1.000000, 1.000000, 0.000000}, {154, 201, 0.000000, 1.000000, 1.000000, 0.000000}, {155, 198, 0.000000, 1.000000, 1.000000, 0.000000}, {156, 199, 0.000000, 1.000000, 1.000000, 0.000000}, {157, 202, 0.000000, 1.000000, 1.000000, 0.000000}, {158, 203, 0.000000, 1.000000, 1.000000, 0.000000}, {159, 204, 0.000000, 1.000000, 1.000000, 0.000000}, {160, 205, 0.000000, 1.000000, 1.000000, 0.000000}, {161, 206, 0.000000, 1.000000, 1.000000, 0.000000}, {162, 207, 0.000000, 0.200000, 5.000000, 0.000000}, {162, 207, 0.200000, 0.400000, -5.000000, 2.000000}, {162, 208, 0.200000, 0.400000, 5.000000, -1.000000}, {162, 208, 0.400000, 0.600000, -5.000000, 3.000000}, {162, 209, 0.400000, 0.600000, 5.000000, -2.000000}, {162, 209, 0.600000, 0.800000, -5.000000, 4.000000}, {162, 210, 0.600000, 0.800000, 5.000000, -3.000000}, {162, 210, 0.800000, 1.000000, -5.000000, 5.000000}, {163, 211, 0.000000, 1.000000, 1.000000, 0.000000}, {164, 212, 0.000000, 1.000000, 1.000000, 0.000000}, {165, 213, -1.000000, 0.000000, -1.000000, 0.000000}, {165, 214, 0.000000, 1.000000, 1.000000, 0.000000}, {166, 215, -1.000000, 0.000000, -1.000000, 0.000000}, {166, 216, 0.000000, 1.000000, 1.000000, 0.000000}, {167, 217, -1.000000, 0.000000, -1.000000, 0.000000}, {167, 218, 0.000000, 1.000000, 1.000000, 0.000000}, {168, 219, 0.000000, 1.000000, 1.000000, 0.000000}, {168, 221, -1.000000, 0.000000, -1.000000, 0.000000}, {169, 223, 0.000000, 1.000000, 1.000000, 0.000000}, {169, 225, -1.000000, 0.000000, -1.000000, 0.000000}, {170, 229, 0.000000, 1.000000, 1.000000, 0.000000}, {170, 227, -1.000000, 0.000000, -1.000000, 0.000000}, {171, 220, 0.000000, 1.000000, 1.000000, 0.000000}, {171, 222, -1.000000, 0.000000, -1.000000, 0.000000}, {172, 224, 0.000000, 1.000000, 1.000000, 0.000000}, {172, 226, -1.000000, 0.000000, -1.000000, 0.000000}, {173, 230, 0.000000, 1.000000, 1.000000, 0.000000}, {173, 228, -1.000000, 0.000000, -1.000000, 0.000000}, }; const TArray> GuiControlRanges = { {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {-1.000000, 1.000000}, {-1.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {-1.000000, 1.000000}, {-1.000000, 1.000000}, {-1.000000, 1.000000}, {-1.000000, 1.000000}, {-1.000000, 1.000000}, {-1.000000, 1.000000}, {-1.000000, 1.000000}, {-1.000000, 1.000000}, {-1.000000, 1.000000}, {-1.000000, 1.000000}, {0.000000, 1.000000}, {-1.000000, 1.000000}, {-1.000000, 1.000000}, {-1.000000, 1.000000}, {-1.000000, 1.000000}, {-1.000000, 1.000000}, {-1.000000, 1.000000}, {-1.000000, 1.000000}, {-1.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {-1.000000, 1.000000}, {-1.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {-1.000000, 1.000000}, {-1.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {-1.000000, 1.000000}, {-1.000000, 1.000000}, {-1.000000, 1.000000}, {-1.000000, 1.000000}, {-1.000000, 1.000000}, {-1.000000, 1.000000}, {-1.000000, 1.000000}, {-1.000000, 1.000000}, {-1.000000, 1.000000}, {-1.000000, 1.000000}, {-1.000000, 1.000000}, {-1.000000, 1.000000}, {-1.000000, 1.000000}, {-1.000000, 1.000000}, {-1.000000, 1.000000}, {-1.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {-1.000000, 1.000000}, {-1.000000, 1.000000}, {-1.000000, 1.000000}, {-1.000000, 1.000000}, {-1.000000, 1.000000}, {-1.000000, 1.000000}, {-1.000000, 1.000000}, {-1.000000, 1.000000}, {-1.000000, 1.000000}, {-1.000000, 1.000000}, {-1.000000, 1.000000}, {-1.000000, 1.000000}, {-1.000000, 1.000000}, {0.000000, 1.000000}, {-1.000000, 1.000000}, {-1.000000, 1.000000}, {-1.000000, 1.000000}, {0.000000, 1.000000}, {-1.000000, 1.000000}, {-1.000000, 1.000000}, {-1.000000, 1.000000}, {0.000000, 1.000000}, {-1.000000, 1.000000}, {-1.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {0.000000, 1.000000}, {-1.000000, 1.000000}, {-1.000000, 1.000000}, {-1.000000, 1.000000}, {-1.000000, 1.000000}, {-1.000000, 1.000000}, {-1.000000, 1.000000}, {-1.000000, 1.000000}, {-1.000000, 1.000000}, {-1.000000, 1.000000}, }; const GuiControlsArray DefaultGuiValues{ 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 1.000000, 1.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, }; GuiControlsArray ConvertGuiControlsToArray(const TMap& InGuiControls) { GuiControlsArray GuiControls; GuiControls.Reserve(NumGuiControls); for (int32 GuiNameIndex = 0; GuiNameIndex < NumGuiControls; ++GuiNameIndex) { if (const float* GuiValue = InGuiControls.Find(DefaultGuiNames[GuiNameIndex])) { GuiControls.Add(*GuiValue); } else { GuiControls.Add(DefaultGuiValues[GuiNameIndex]); } } return GuiControls; } TMap ConvertRawControlsToMap(const RawControlsArray& InRawControls) { TMap RawControlsMap; RawControlsMap.Reserve(NumRawControls); for (int32 RawNameIndex = 0; RawNameIndex < NumRawControls; ++RawNameIndex) { RawControlsMap.Add(DefaultRawControlNames[RawNameIndex], InRawControls[RawNameIndex]); } return RawControlsMap; } TMap ConvertGuiToRawControls(const TMap& InGuiControls) { // Convert gui controls to array with default values if needed const GuiControlsArray GuiControlsArray = ConvertGuiControlsToArray(InGuiControls); RawControlsArray RawControlsArray; RawControlsArray.Init(0.0, NumRawControls); for (int32 MappingIndex = 0; MappingIndex < GuiToRawMappings.Num(); ++MappingIndex) { const GuiToRawControlInfo& GuiMapping = GuiToRawMappings[MappingIndex]; const float RangeStart = GuiControlRanges[GuiMapping.InputIndex].Key; const float RangeEnd = GuiControlRanges[GuiMapping.InputIndex].Value; const float GuiValue = GuiControlsArray[GuiMapping.InputIndex]; const bool bIsBelowRange = GuiMapping.From == RangeStart && GuiValue < GuiMapping.From; const bool bIsAboveRange = GuiMapping.To == RangeEnd && GuiValue >= GuiMapping.To; if ((GuiMapping.From <= GuiValue) && (GuiValue < GuiMapping.To)) { RawControlsArray[GuiMapping.OutputIndex] += GuiMapping.Slope * GuiValue + GuiMapping.Cut; } else if (bIsBelowRange) { RawControlsArray[GuiMapping.OutputIndex] += GuiMapping.Slope * GuiMapping.From + GuiMapping.Cut; // clamp to minimum range value } else if (bIsAboveRange) { RawControlsArray[GuiMapping.OutputIndex] += GuiMapping.Slope * GuiMapping.To + GuiMapping.Cut; // clamp to maximum range value } } TMap OutRawControls = ConvertRawControlsToMap(RawControlsArray); return OutRawControls; } } FAnimNode_BlendRealisticMetaHumanLipSync::FAnimNode_BlendRealisticMetaHumanLipSync() { // Initialize with default values TArray ControlNames = URealisticMetaHumanLipSyncGenerator::GetControlNames(); for (const FString& ControlName : ControlNames) { TargetControlValues.Add(ControlName, 0.0f); CurrentControlValues.Add(ControlName, 0.0f); IdleStateValues.Add(ControlName, 0.0f); } } void FAnimNode_BlendRealisticMetaHumanLipSync::Initialize_AnyThread(const FAnimationInitializeContext& Context) { SourcePose.Initialize(Context); } void FAnimNode_BlendRealisticMetaHumanLipSync::CacheBones_AnyThread(const FAnimationCacheBonesContext& Context) { SourcePose.CacheBones(Context); } void FAnimNode_BlendRealisticMetaHumanLipSync::Update_AnyThread(const FAnimationUpdateContext& Context) { SourcePose.Update(Context); GetEvaluateGraphExposedInputs().Execute(Context); // Get the latest control values from the generator if (LipSyncGenerator.IsValid()) { TMap NewControlValues = LipSyncGenerator->GetControlValues(); // Check if control values have changed bool bValuesChanged = false; for (const auto& Pair : NewControlValues) { float* OldValue = TargetControlValues.Find(Pair.Key); if (!OldValue || FMath::Abs(*OldValue - Pair.Value) > KINDA_SMALL_NUMBER) { bValuesChanged = true; break; } } if (bValuesChanged) { // Update target values and reset timer TargetControlValues = NewControlValues; TimeSinceLastChange = 0.0f; // Update idle state preservation with current active expressions UpdateIdleStatePreservation(); } else { // Increment time since last change TimeSinceLastChange += Context.GetDeltaTime(); // Reset to idle state if no change for specified duration if (TimeSinceLastChange >= ResetTime) { // Instead of directly setting values, smoothly transition to idle state for (auto& Pair : TargetControlValues) { float IdleValue; if (bPreserveIdleState && ShouldPreserveControl(Pair.Key)) { // Use preserved idle state value instead of zero IdleValue = IdleStateValues[Pair.Key]; } else { // Reset to neutral for non-preserved controls IdleValue = 0.0f; } // Only update target if it's different from current target // This prevents constant updates during idle state if (FMath::Abs(Pair.Value - IdleValue) > KINDA_SMALL_NUMBER) { Pair.Value = IdleValue; } } // Update the generator with the new idle target values LipSyncGenerator->SetControlValues(TargetControlValues); } } } // Smoothly interpolate current values towards target values // This interpolation applies to both active speech and idle transitions const float DeltaTime = Context.GetDeltaTime(); // Use different interpolation speeds for active speech vs idle transitions const float EffectiveInterpolationSpeed = (TimeSinceLastChange >= ResetTime) ? IdleInterpolationSpeed : InterpolationSpeed; for (auto& Pair : CurrentControlValues) { const FString& ControlName = Pair.Key; float& CurrentValue = Pair.Value; float TargetValue = 0.0f; if (float* FoundValue = TargetControlValues.Find(ControlName)) { TargetValue = *FoundValue; } CurrentValue = FMath::FInterpTo(CurrentValue, TargetValue, DeltaTime, EffectiveInterpolationSpeed); } } void FAnimNode_BlendRealisticMetaHumanLipSync::Evaluate_AnyThread(FPoseContext& Output) { // Evaluate the source pose SourcePose.Evaluate(Output); const TMap SolverControlMap = RuntimeLipSync_GuiToRawControlsUtils::ConvertGuiToRawControls(CurrentControlValues); // Apply the control values to the animation curves for (const auto& Pair : SolverControlMap) { if (!RuntimeLipSync_GuiToRawControlsUtils::EyesCurveNames.Find(Pair.Key)) { #if UE_VERSION_OLDER_THAN(5, 3, 0) USkeleton* Skeleton = Output.AnimInstanceProxy->GetSkeleton(); SmartName::UID_Type NameUID = Skeleton->GetUIDByName(USkeleton::AnimCurveMappingName, *Pair.Key); if (NameUID == SmartName::MaxUID) { continue; } Output.Curve.Set(NameUID, Pair.Value); #else Output.Curve.Set(*Pair.Key, Pair.Value); #endif } } } void FAnimNode_BlendRealisticMetaHumanLipSync::GatherDebugData(FNodeDebugData& DebugData) { FString DebugLine = FString::Printf(TEXT("Blend Realistic MetaHuman Lip Sync")); DebugData.AddDebugItem(DebugLine); SourcePose.GatherDebugData(DebugData.BranchFlow(1.0f)); } bool FAnimNode_BlendRealisticMetaHumanLipSync::ShouldPreserveControl(const FString& ControlName) const { if (!bPreserveIdleState) { return false; } // Eye-related controls if (bPreserveEyeExpressions && ( ControlName.Contains(TEXT("eye")) || ControlName.Contains(TEXT("Eye")) || ControlName.Contains(TEXT("eyelid")) || ControlName.Contains(TEXT("eyelash")) )) { return true; } // Brow-related controls if (bPreserveBrowExpressions && ( ControlName.Contains(TEXT("brow")) || ControlName.Contains(TEXT("Brow")) )) { return true; } // Mouth shape controls (excluding speech-specific movements) if (bPreserveMouthShape && ( ControlName.Contains(TEXT("mouth")) || ControlName.Contains(TEXT("Mouth")) )) { // Exclude speech-specific mouth controls that should reset if (ControlName.Contains(TEXT("tongue")) || ControlName.Contains(TEXT("Tongue")) || ControlName.Contains(TEXT("jaw")) || ControlName.Contains(TEXT("Jaw"))) { return false; } return true; } return false; } void FAnimNode_BlendRealisticMetaHumanLipSync::UpdateIdleStatePreservation() { if (!bPreserveIdleState) { return; } // Update idle state values with current non-zero values that should be preserved for (const auto& Pair : CurrentControlValues) { if (ShouldPreserveControl(Pair.Key) && FMath::Abs(Pair.Value) > KINDA_SMALL_NUMBER) { IdleStateValues[Pair.Key] = Pair.Value; } } }