├── AndroidFaceCapture.uproject ├── Config ├── DefaultEditor.ini ├── DefaultEngine.ini └── DefaultGame.ini ├── Content ├── BlendShapes │ ├── BlendWeightsSharing.uasset │ ├── EyeBrowsCheeksNose │ │ ├── browDownLeft.uasset │ │ ├── browDownRight.uasset │ │ ├── browInnerUp.uasset │ │ ├── browOuterUpLeft.uasset │ │ ├── browOuterUpRight.uasset │ │ ├── cheekPuff.uasset │ │ ├── cheekSquintLeft.uasset │ │ ├── cheekSquintRight.uasset │ │ ├── noseSneerLeft.uasset │ │ └── noseSneerRight.uasset │ ├── LeftEye │ │ ├── eyeBlinkLeft.uasset │ │ ├── eyeLookDownLeft.uasset │ │ ├── eyeLookInLeft.uasset │ │ ├── eyeLookOutLeft.uasset │ │ ├── eyeLookUpLeft.uasset │ │ ├── eyeSquintLeft.uasset │ │ └── eyeWideLeft.uasset │ ├── MouthJaw │ │ ├── jawForward.uasset │ │ ├── jawLeft.uasset │ │ ├── jawOpen.uasset │ │ ├── jawRight.uasset │ │ ├── mouthClose.uasset │ │ ├── mouthDimpleLeft.uasset │ │ ├── mouthDimpleRight.uasset │ │ ├── mouthFrownLeft.uasset │ │ ├── mouthFrownRight.uasset │ │ ├── mouthFunnel.uasset │ │ ├── mouthLeft.uasset │ │ ├── mouthLowerDownLeft.uasset │ │ ├── mouthLowerDownRight.uasset │ │ ├── mouthPressLeft.uasset │ │ ├── mouthPressRight.uasset │ │ ├── mouthPucker.uasset │ │ ├── mouthRight.uasset │ │ ├── mouthRollLower.uasset │ │ ├── mouthRollUpper.uasset │ │ ├── mouthShrugLower.uasset │ │ ├── mouthShrugUpper.uasset │ │ ├── mouthSmileLeft.uasset │ │ ├── mouthSmileRight.uasset │ │ ├── mouthStretchLeft.uasset │ │ ├── mouthStretchRight.uasset │ │ ├── mouthUpperUpLeft.uasset │ │ └── mouthUpperUpRight.uasset │ ├── PingPongLiveLink.uasset │ ├── Reference.uasset │ └── RightEye │ │ ├── eyeBlinkRight.uasset │ │ ├── eyeLookDownRight.uasset │ │ ├── eyeLookInRight.uasset │ │ ├── eyeLookOutRight.uasset │ │ ├── eyeLookUpRight.uasset │ │ ├── eyeSquintRight.uasset │ │ └── eyeWideRight.uasset ├── Blueprint │ ├── AndroidLiveLinkSubject.uasset │ ├── BP_BlendShapesHandler.uasset │ ├── BP_ReceiveAndroidFaceData.uasset │ ├── FacePoints.uasset │ ├── M_Unlit.uasset │ ├── M_Unlit_Inst.uasset │ └── Reader.uasset ├── Maps │ ├── DemoMain426.umap │ └── DemoMain426_BuiltData.uasset └── Widget │ └── BlendShapeSelector.uasset ├── LICENSE ├── README.md ├── Resources ├── face-scan2_128.png ├── face-scan2_16.png ├── face-scan_128.png └── face-scan_16.png └── Source ├── AndroidFaceCapture.Target.cs ├── AndroidFaceCapture ├── AndroidFaceCapture.Build.cs ├── AndroidFaceCapture.cpp ├── AndroidFaceCapture.h ├── AndroidFaceCaptureGameModeBase.cpp ├── AndroidFaceCaptureGameModeBase.h ├── Private │ ├── AndroidBlenshape.cpp │ ├── EditorTickingActors.cpp │ ├── LiveLink │ │ └── VirtualAndroidARLiveLinkSubject.cpp │ └── TCP_Data_Receiver.cpp └── Public │ ├── AndroidBlenshape.h │ ├── EditorTickingActors.h │ ├── LiveLink │ └── VirtualAndroidARLiveLinkSubject.h │ └── TCP_Data_Receiver.h ├── AndroidFaceCaptureEditor.Target.cs └── AndroidFaceCaptureEditor ├── AndroidBlenshapeAssetTypeActions.cpp ├── AndroidBlenshapeAssetTypeActions.h ├── AndroidBlenshapeFactory.cpp ├── AndroidBlenshapeFactory.h ├── AndroidFaceCaptureEditor.Build.cs ├── AndroidFaceCaptureEditor.cpp └── AndroidFaceCaptureEditor.h /AndroidFaceCapture.uproject: -------------------------------------------------------------------------------- 1 | { 2 | "FileVersion": 3, 3 | "EngineAssociation": "{6FF5F6FA-4302-6727-B2BE-989513BA8B61}", 4 | "Category": "", 5 | "Description": "", 6 | "Modules": [ 7 | { 8 | "Name": "AndroidFaceCapture", 9 | "Type": "Runtime", 10 | "LoadingPhase": "PostConfigInit", 11 | "AdditionalDependencies": [ 12 | "TcpSocketPlugin", 13 | "CoreUObject", 14 | "Engine", 15 | "LiveLinkInterface" 16 | ] 17 | }, 18 | { 19 | "Name": "AndroidFaceCaptureEditor", 20 | "Type": "Editor", 21 | "LoadingPhase": "PostEngineInit" 22 | } 23 | ], 24 | "Plugins": [ 25 | { 26 | "Name": "TcpSocketPlugin", 27 | "Enabled": true, 28 | "MarketplaceURL": "com.epicgames.launcher://ue/marketplace/content/462c2952e71c4548ae324cb624c74aa6" 29 | }, 30 | { 31 | "Name": "LiveLink", 32 | "Enabled": true 33 | }, 34 | { 35 | "Name": "HairStrands", 36 | "Enabled": true 37 | }, 38 | { 39 | "Name": "RigLogic", 40 | "Enabled": true 41 | }, 42 | { 43 | "Name": "LiveLinkControlRig", 44 | "Enabled": true 45 | }, 46 | { 47 | "Name": "SequencerScripting", 48 | "Enabled": true 49 | } 50 | ] 51 | } -------------------------------------------------------------------------------- /Config/DefaultEditor.ini: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Config/DefaultEngine.ini: -------------------------------------------------------------------------------- 1 | [/Script/EngineSettings.GameMapsSettings] 2 | GameDefaultMap=/Engine/Maps/Templates/Template_Default.Template_Default 3 | EditorStartupMap=/Game/Maps/DemoMain426.DemoMain426 4 | 5 | [/Script/HardwareTargeting.HardwareTargetingSettings] 6 | TargetedHardwareClass=Desktop 7 | AppliedTargetedHardwareClass=Desktop 8 | DefaultGraphicsPerformance=Maximum 9 | AppliedDefaultGraphicsPerformance=Maximum 10 | 11 | [/Script/Engine.Engine] 12 | +ActiveGameNameRedirects=(OldGameName="TP_Blank",NewGameName="/Script/AndroidFaceCapture") 13 | +ActiveGameNameRedirects=(OldGameName="/Script/TP_Blank",NewGameName="/Script/AndroidFaceCapture") 14 | +ActiveClassRedirects=(OldClassName="TP_BlankGameModeBase",NewClassName="AndroidFaceCaptureGameModeBase") 15 | 16 | [ConsoleVariables] 17 | fx.Niagara.ForceLastTickGroup=1 18 | 19 | [/Script/Engine.RendererSettings] 20 | r.GPUSkin.Support16BitBoneIndex=True 21 | r.GPUSkin.UnlimitedBoneInfluences=True 22 | r.SkinCache.BlendUsingVertexColorForRecomputeTangents=2 23 | r.SkinCache.CompileShaders=True 24 | r.SkinCache.DefaultBehavior=0 25 | SkeletalMesh.UseExperimentalChunking=1 26 | 27 | -------------------------------------------------------------------------------- /Config/DefaultGame.ini: -------------------------------------------------------------------------------- 1 | 2 | [/Script/EngineSettings.GeneralProjectSettings] 3 | ProjectID=FD168DC744C9DBB398D120A4A0D07139 4 | -------------------------------------------------------------------------------- /Content/BlendShapes/BlendWeightsSharing.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaximeDup/FaceCaptureUnrealEngine/c159662643f4fd4bc6069dd3fc186abb39966991/Content/BlendShapes/BlendWeightsSharing.uasset -------------------------------------------------------------------------------- /Content/BlendShapes/EyeBrowsCheeksNose/browDownLeft.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaximeDup/FaceCaptureUnrealEngine/c159662643f4fd4bc6069dd3fc186abb39966991/Content/BlendShapes/EyeBrowsCheeksNose/browDownLeft.uasset -------------------------------------------------------------------------------- /Content/BlendShapes/EyeBrowsCheeksNose/browDownRight.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaximeDup/FaceCaptureUnrealEngine/c159662643f4fd4bc6069dd3fc186abb39966991/Content/BlendShapes/EyeBrowsCheeksNose/browDownRight.uasset -------------------------------------------------------------------------------- /Content/BlendShapes/EyeBrowsCheeksNose/browInnerUp.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaximeDup/FaceCaptureUnrealEngine/c159662643f4fd4bc6069dd3fc186abb39966991/Content/BlendShapes/EyeBrowsCheeksNose/browInnerUp.uasset -------------------------------------------------------------------------------- /Content/BlendShapes/EyeBrowsCheeksNose/browOuterUpLeft.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaximeDup/FaceCaptureUnrealEngine/c159662643f4fd4bc6069dd3fc186abb39966991/Content/BlendShapes/EyeBrowsCheeksNose/browOuterUpLeft.uasset -------------------------------------------------------------------------------- /Content/BlendShapes/EyeBrowsCheeksNose/browOuterUpRight.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaximeDup/FaceCaptureUnrealEngine/c159662643f4fd4bc6069dd3fc186abb39966991/Content/BlendShapes/EyeBrowsCheeksNose/browOuterUpRight.uasset -------------------------------------------------------------------------------- /Content/BlendShapes/EyeBrowsCheeksNose/cheekPuff.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaximeDup/FaceCaptureUnrealEngine/c159662643f4fd4bc6069dd3fc186abb39966991/Content/BlendShapes/EyeBrowsCheeksNose/cheekPuff.uasset -------------------------------------------------------------------------------- /Content/BlendShapes/EyeBrowsCheeksNose/cheekSquintLeft.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaximeDup/FaceCaptureUnrealEngine/c159662643f4fd4bc6069dd3fc186abb39966991/Content/BlendShapes/EyeBrowsCheeksNose/cheekSquintLeft.uasset -------------------------------------------------------------------------------- /Content/BlendShapes/EyeBrowsCheeksNose/cheekSquintRight.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaximeDup/FaceCaptureUnrealEngine/c159662643f4fd4bc6069dd3fc186abb39966991/Content/BlendShapes/EyeBrowsCheeksNose/cheekSquintRight.uasset -------------------------------------------------------------------------------- /Content/BlendShapes/EyeBrowsCheeksNose/noseSneerLeft.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaximeDup/FaceCaptureUnrealEngine/c159662643f4fd4bc6069dd3fc186abb39966991/Content/BlendShapes/EyeBrowsCheeksNose/noseSneerLeft.uasset -------------------------------------------------------------------------------- /Content/BlendShapes/EyeBrowsCheeksNose/noseSneerRight.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaximeDup/FaceCaptureUnrealEngine/c159662643f4fd4bc6069dd3fc186abb39966991/Content/BlendShapes/EyeBrowsCheeksNose/noseSneerRight.uasset -------------------------------------------------------------------------------- /Content/BlendShapes/LeftEye/eyeBlinkLeft.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaximeDup/FaceCaptureUnrealEngine/c159662643f4fd4bc6069dd3fc186abb39966991/Content/BlendShapes/LeftEye/eyeBlinkLeft.uasset -------------------------------------------------------------------------------- /Content/BlendShapes/LeftEye/eyeLookDownLeft.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaximeDup/FaceCaptureUnrealEngine/c159662643f4fd4bc6069dd3fc186abb39966991/Content/BlendShapes/LeftEye/eyeLookDownLeft.uasset -------------------------------------------------------------------------------- /Content/BlendShapes/LeftEye/eyeLookInLeft.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaximeDup/FaceCaptureUnrealEngine/c159662643f4fd4bc6069dd3fc186abb39966991/Content/BlendShapes/LeftEye/eyeLookInLeft.uasset -------------------------------------------------------------------------------- /Content/BlendShapes/LeftEye/eyeLookOutLeft.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaximeDup/FaceCaptureUnrealEngine/c159662643f4fd4bc6069dd3fc186abb39966991/Content/BlendShapes/LeftEye/eyeLookOutLeft.uasset -------------------------------------------------------------------------------- /Content/BlendShapes/LeftEye/eyeLookUpLeft.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaximeDup/FaceCaptureUnrealEngine/c159662643f4fd4bc6069dd3fc186abb39966991/Content/BlendShapes/LeftEye/eyeLookUpLeft.uasset -------------------------------------------------------------------------------- /Content/BlendShapes/LeftEye/eyeSquintLeft.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaximeDup/FaceCaptureUnrealEngine/c159662643f4fd4bc6069dd3fc186abb39966991/Content/BlendShapes/LeftEye/eyeSquintLeft.uasset -------------------------------------------------------------------------------- /Content/BlendShapes/LeftEye/eyeWideLeft.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaximeDup/FaceCaptureUnrealEngine/c159662643f4fd4bc6069dd3fc186abb39966991/Content/BlendShapes/LeftEye/eyeWideLeft.uasset -------------------------------------------------------------------------------- /Content/BlendShapes/MouthJaw/jawForward.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaximeDup/FaceCaptureUnrealEngine/c159662643f4fd4bc6069dd3fc186abb39966991/Content/BlendShapes/MouthJaw/jawForward.uasset -------------------------------------------------------------------------------- /Content/BlendShapes/MouthJaw/jawLeft.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaximeDup/FaceCaptureUnrealEngine/c159662643f4fd4bc6069dd3fc186abb39966991/Content/BlendShapes/MouthJaw/jawLeft.uasset -------------------------------------------------------------------------------- /Content/BlendShapes/MouthJaw/jawOpen.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaximeDup/FaceCaptureUnrealEngine/c159662643f4fd4bc6069dd3fc186abb39966991/Content/BlendShapes/MouthJaw/jawOpen.uasset -------------------------------------------------------------------------------- /Content/BlendShapes/MouthJaw/jawRight.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaximeDup/FaceCaptureUnrealEngine/c159662643f4fd4bc6069dd3fc186abb39966991/Content/BlendShapes/MouthJaw/jawRight.uasset -------------------------------------------------------------------------------- /Content/BlendShapes/MouthJaw/mouthClose.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaximeDup/FaceCaptureUnrealEngine/c159662643f4fd4bc6069dd3fc186abb39966991/Content/BlendShapes/MouthJaw/mouthClose.uasset -------------------------------------------------------------------------------- /Content/BlendShapes/MouthJaw/mouthDimpleLeft.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaximeDup/FaceCaptureUnrealEngine/c159662643f4fd4bc6069dd3fc186abb39966991/Content/BlendShapes/MouthJaw/mouthDimpleLeft.uasset -------------------------------------------------------------------------------- /Content/BlendShapes/MouthJaw/mouthDimpleRight.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaximeDup/FaceCaptureUnrealEngine/c159662643f4fd4bc6069dd3fc186abb39966991/Content/BlendShapes/MouthJaw/mouthDimpleRight.uasset -------------------------------------------------------------------------------- /Content/BlendShapes/MouthJaw/mouthFrownLeft.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaximeDup/FaceCaptureUnrealEngine/c159662643f4fd4bc6069dd3fc186abb39966991/Content/BlendShapes/MouthJaw/mouthFrownLeft.uasset -------------------------------------------------------------------------------- /Content/BlendShapes/MouthJaw/mouthFrownRight.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaximeDup/FaceCaptureUnrealEngine/c159662643f4fd4bc6069dd3fc186abb39966991/Content/BlendShapes/MouthJaw/mouthFrownRight.uasset -------------------------------------------------------------------------------- /Content/BlendShapes/MouthJaw/mouthFunnel.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaximeDup/FaceCaptureUnrealEngine/c159662643f4fd4bc6069dd3fc186abb39966991/Content/BlendShapes/MouthJaw/mouthFunnel.uasset -------------------------------------------------------------------------------- /Content/BlendShapes/MouthJaw/mouthLeft.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaximeDup/FaceCaptureUnrealEngine/c159662643f4fd4bc6069dd3fc186abb39966991/Content/BlendShapes/MouthJaw/mouthLeft.uasset -------------------------------------------------------------------------------- /Content/BlendShapes/MouthJaw/mouthLowerDownLeft.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaximeDup/FaceCaptureUnrealEngine/c159662643f4fd4bc6069dd3fc186abb39966991/Content/BlendShapes/MouthJaw/mouthLowerDownLeft.uasset -------------------------------------------------------------------------------- /Content/BlendShapes/MouthJaw/mouthLowerDownRight.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaximeDup/FaceCaptureUnrealEngine/c159662643f4fd4bc6069dd3fc186abb39966991/Content/BlendShapes/MouthJaw/mouthLowerDownRight.uasset -------------------------------------------------------------------------------- /Content/BlendShapes/MouthJaw/mouthPressLeft.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaximeDup/FaceCaptureUnrealEngine/c159662643f4fd4bc6069dd3fc186abb39966991/Content/BlendShapes/MouthJaw/mouthPressLeft.uasset -------------------------------------------------------------------------------- /Content/BlendShapes/MouthJaw/mouthPressRight.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaximeDup/FaceCaptureUnrealEngine/c159662643f4fd4bc6069dd3fc186abb39966991/Content/BlendShapes/MouthJaw/mouthPressRight.uasset -------------------------------------------------------------------------------- /Content/BlendShapes/MouthJaw/mouthPucker.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaximeDup/FaceCaptureUnrealEngine/c159662643f4fd4bc6069dd3fc186abb39966991/Content/BlendShapes/MouthJaw/mouthPucker.uasset -------------------------------------------------------------------------------- /Content/BlendShapes/MouthJaw/mouthRight.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaximeDup/FaceCaptureUnrealEngine/c159662643f4fd4bc6069dd3fc186abb39966991/Content/BlendShapes/MouthJaw/mouthRight.uasset -------------------------------------------------------------------------------- /Content/BlendShapes/MouthJaw/mouthRollLower.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaximeDup/FaceCaptureUnrealEngine/c159662643f4fd4bc6069dd3fc186abb39966991/Content/BlendShapes/MouthJaw/mouthRollLower.uasset -------------------------------------------------------------------------------- /Content/BlendShapes/MouthJaw/mouthRollUpper.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaximeDup/FaceCaptureUnrealEngine/c159662643f4fd4bc6069dd3fc186abb39966991/Content/BlendShapes/MouthJaw/mouthRollUpper.uasset -------------------------------------------------------------------------------- /Content/BlendShapes/MouthJaw/mouthShrugLower.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaximeDup/FaceCaptureUnrealEngine/c159662643f4fd4bc6069dd3fc186abb39966991/Content/BlendShapes/MouthJaw/mouthShrugLower.uasset -------------------------------------------------------------------------------- /Content/BlendShapes/MouthJaw/mouthShrugUpper.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaximeDup/FaceCaptureUnrealEngine/c159662643f4fd4bc6069dd3fc186abb39966991/Content/BlendShapes/MouthJaw/mouthShrugUpper.uasset -------------------------------------------------------------------------------- /Content/BlendShapes/MouthJaw/mouthSmileLeft.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaximeDup/FaceCaptureUnrealEngine/c159662643f4fd4bc6069dd3fc186abb39966991/Content/BlendShapes/MouthJaw/mouthSmileLeft.uasset -------------------------------------------------------------------------------- /Content/BlendShapes/MouthJaw/mouthSmileRight.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaximeDup/FaceCaptureUnrealEngine/c159662643f4fd4bc6069dd3fc186abb39966991/Content/BlendShapes/MouthJaw/mouthSmileRight.uasset -------------------------------------------------------------------------------- /Content/BlendShapes/MouthJaw/mouthStretchLeft.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaximeDup/FaceCaptureUnrealEngine/c159662643f4fd4bc6069dd3fc186abb39966991/Content/BlendShapes/MouthJaw/mouthStretchLeft.uasset -------------------------------------------------------------------------------- /Content/BlendShapes/MouthJaw/mouthStretchRight.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaximeDup/FaceCaptureUnrealEngine/c159662643f4fd4bc6069dd3fc186abb39966991/Content/BlendShapes/MouthJaw/mouthStretchRight.uasset -------------------------------------------------------------------------------- /Content/BlendShapes/MouthJaw/mouthUpperUpLeft.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaximeDup/FaceCaptureUnrealEngine/c159662643f4fd4bc6069dd3fc186abb39966991/Content/BlendShapes/MouthJaw/mouthUpperUpLeft.uasset -------------------------------------------------------------------------------- /Content/BlendShapes/MouthJaw/mouthUpperUpRight.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaximeDup/FaceCaptureUnrealEngine/c159662643f4fd4bc6069dd3fc186abb39966991/Content/BlendShapes/MouthJaw/mouthUpperUpRight.uasset -------------------------------------------------------------------------------- /Content/BlendShapes/PingPongLiveLink.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaximeDup/FaceCaptureUnrealEngine/c159662643f4fd4bc6069dd3fc186abb39966991/Content/BlendShapes/PingPongLiveLink.uasset -------------------------------------------------------------------------------- /Content/BlendShapes/Reference.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaximeDup/FaceCaptureUnrealEngine/c159662643f4fd4bc6069dd3fc186abb39966991/Content/BlendShapes/Reference.uasset -------------------------------------------------------------------------------- /Content/BlendShapes/RightEye/eyeBlinkRight.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaximeDup/FaceCaptureUnrealEngine/c159662643f4fd4bc6069dd3fc186abb39966991/Content/BlendShapes/RightEye/eyeBlinkRight.uasset -------------------------------------------------------------------------------- /Content/BlendShapes/RightEye/eyeLookDownRight.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaximeDup/FaceCaptureUnrealEngine/c159662643f4fd4bc6069dd3fc186abb39966991/Content/BlendShapes/RightEye/eyeLookDownRight.uasset -------------------------------------------------------------------------------- /Content/BlendShapes/RightEye/eyeLookInRight.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaximeDup/FaceCaptureUnrealEngine/c159662643f4fd4bc6069dd3fc186abb39966991/Content/BlendShapes/RightEye/eyeLookInRight.uasset -------------------------------------------------------------------------------- /Content/BlendShapes/RightEye/eyeLookOutRight.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaximeDup/FaceCaptureUnrealEngine/c159662643f4fd4bc6069dd3fc186abb39966991/Content/BlendShapes/RightEye/eyeLookOutRight.uasset -------------------------------------------------------------------------------- /Content/BlendShapes/RightEye/eyeLookUpRight.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaximeDup/FaceCaptureUnrealEngine/c159662643f4fd4bc6069dd3fc186abb39966991/Content/BlendShapes/RightEye/eyeLookUpRight.uasset -------------------------------------------------------------------------------- /Content/BlendShapes/RightEye/eyeSquintRight.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaximeDup/FaceCaptureUnrealEngine/c159662643f4fd4bc6069dd3fc186abb39966991/Content/BlendShapes/RightEye/eyeSquintRight.uasset -------------------------------------------------------------------------------- /Content/BlendShapes/RightEye/eyeWideRight.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaximeDup/FaceCaptureUnrealEngine/c159662643f4fd4bc6069dd3fc186abb39966991/Content/BlendShapes/RightEye/eyeWideRight.uasset -------------------------------------------------------------------------------- /Content/Blueprint/AndroidLiveLinkSubject.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaximeDup/FaceCaptureUnrealEngine/c159662643f4fd4bc6069dd3fc186abb39966991/Content/Blueprint/AndroidLiveLinkSubject.uasset -------------------------------------------------------------------------------- /Content/Blueprint/BP_BlendShapesHandler.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaximeDup/FaceCaptureUnrealEngine/c159662643f4fd4bc6069dd3fc186abb39966991/Content/Blueprint/BP_BlendShapesHandler.uasset -------------------------------------------------------------------------------- /Content/Blueprint/BP_ReceiveAndroidFaceData.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaximeDup/FaceCaptureUnrealEngine/c159662643f4fd4bc6069dd3fc186abb39966991/Content/Blueprint/BP_ReceiveAndroidFaceData.uasset -------------------------------------------------------------------------------- /Content/Blueprint/FacePoints.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaximeDup/FaceCaptureUnrealEngine/c159662643f4fd4bc6069dd3fc186abb39966991/Content/Blueprint/FacePoints.uasset -------------------------------------------------------------------------------- /Content/Blueprint/M_Unlit.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaximeDup/FaceCaptureUnrealEngine/c159662643f4fd4bc6069dd3fc186abb39966991/Content/Blueprint/M_Unlit.uasset -------------------------------------------------------------------------------- /Content/Blueprint/M_Unlit_Inst.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaximeDup/FaceCaptureUnrealEngine/c159662643f4fd4bc6069dd3fc186abb39966991/Content/Blueprint/M_Unlit_Inst.uasset -------------------------------------------------------------------------------- /Content/Blueprint/Reader.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaximeDup/FaceCaptureUnrealEngine/c159662643f4fd4bc6069dd3fc186abb39966991/Content/Blueprint/Reader.uasset -------------------------------------------------------------------------------- /Content/Maps/DemoMain426.umap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaximeDup/FaceCaptureUnrealEngine/c159662643f4fd4bc6069dd3fc186abb39966991/Content/Maps/DemoMain426.umap -------------------------------------------------------------------------------- /Content/Maps/DemoMain426_BuiltData.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaximeDup/FaceCaptureUnrealEngine/c159662643f4fd4bc6069dd3fc186abb39966991/Content/Maps/DemoMain426_BuiltData.uasset -------------------------------------------------------------------------------- /Content/Widget/BlendShapeSelector.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaximeDup/FaceCaptureUnrealEngine/c159662643f4fd4bc6069dd3fc186abb39966991/Content/Widget/BlendShapeSelector.uasset -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Maxime Dupart 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FaceCaptureUnrealEngine 2 | 3 | Leverage AndroidArcoreFacesStreaming to build elementary blend shape weights sent to Unreal Engine Livelink, to articulate MetaHumans or other humanoids. 4 | 5 | Thread: 6 | https://forums.unrealengine.com/t/face-capture-with-android-metahuman-download-links-free-open-source-demo/234927 7 | 8 | ![alt text](https://i.imgur.com/T9EV1fr.png) 9 | 10 | ![alt text](https://i.imgur.com/uC77IqQl.jpg) 11 | -------------------------------------------------------------------------------- /Resources/face-scan2_128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaximeDup/FaceCaptureUnrealEngine/c159662643f4fd4bc6069dd3fc186abb39966991/Resources/face-scan2_128.png -------------------------------------------------------------------------------- /Resources/face-scan2_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaximeDup/FaceCaptureUnrealEngine/c159662643f4fd4bc6069dd3fc186abb39966991/Resources/face-scan2_16.png -------------------------------------------------------------------------------- /Resources/face-scan_128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaximeDup/FaceCaptureUnrealEngine/c159662643f4fd4bc6069dd3fc186abb39966991/Resources/face-scan_128.png -------------------------------------------------------------------------------- /Resources/face-scan_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaximeDup/FaceCaptureUnrealEngine/c159662643f4fd4bc6069dd3fc186abb39966991/Resources/face-scan_16.png -------------------------------------------------------------------------------- /Source/AndroidFaceCapture.Target.cs: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | using UnrealBuildTool; 4 | using System.Collections.Generic; 5 | 6 | public class AndroidFaceCaptureTarget : TargetRules 7 | { 8 | public AndroidFaceCaptureTarget( TargetInfo Target) : base(Target) 9 | { 10 | Type = TargetType.Game; 11 | DefaultBuildSettings = BuildSettingsVersion.V2; 12 | ExtraModuleNames.AddRange( new string[] { "AndroidFaceCapture" } ); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Source/AndroidFaceCapture/AndroidFaceCapture.Build.cs: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | using UnrealBuildTool; 4 | 5 | public class AndroidFaceCapture : ModuleRules 6 | { 7 | public AndroidFaceCapture(ReadOnlyTargetRules Target) : base(Target) 8 | { 9 | PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; 10 | 11 | PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "AugmentedReality" }); 12 | 13 | PrivateDependencyModuleNames.AddRange(new string[] { 14 | "LiveLink", 15 | "LiveLinkInterface"}); 16 | 17 | // Uncomment if you are using Slate UI 18 | // PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" }); 19 | 20 | // Uncomment if you are using online features 21 | // PrivateDependencyModuleNames.Add("OnlineSubsystem"); 22 | 23 | // To include OnlineSubsystemSteam, add it to the plugins section in your uproject file with the Enabled attribute set to true 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Source/AndroidFaceCapture/AndroidFaceCapture.cpp: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | #include "AndroidFaceCapture.h" 4 | #include "Modules/ModuleManager.h" 5 | 6 | IMPLEMENT_PRIMARY_GAME_MODULE( FDefaultGameModuleImpl, AndroidFaceCapture, "AndroidFaceCapture" ); 7 | -------------------------------------------------------------------------------- /Source/AndroidFaceCapture/AndroidFaceCapture.h: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | 7 | -------------------------------------------------------------------------------- /Source/AndroidFaceCapture/AndroidFaceCaptureGameModeBase.cpp: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | 4 | #include "AndroidFaceCaptureGameModeBase.h" 5 | 6 | -------------------------------------------------------------------------------- /Source/AndroidFaceCapture/AndroidFaceCaptureGameModeBase.h: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "GameFramework/GameModeBase.h" 7 | #include "AndroidFaceCaptureGameModeBase.generated.h" 8 | 9 | /** 10 | * 11 | */ 12 | UCLASS() 13 | class ANDROIDFACECAPTURE_API AAndroidFaceCaptureGameModeBase : public AGameModeBase 14 | { 15 | GENERATED_BODY() 16 | 17 | }; 18 | -------------------------------------------------------------------------------- /Source/AndroidFaceCapture/Private/AndroidBlenshape.cpp: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | 4 | #include "AndroidBlenshape.h" 5 | 6 | -------------------------------------------------------------------------------- /Source/AndroidFaceCapture/Private/EditorTickingActors.cpp: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | 4 | #include "EditorTickingActors.h" 5 | #include "Async/ParallelFor.h" 6 | 7 | 8 | // Sets default values 9 | AEditorTickingActors::AEditorTickingActors() 10 | { 11 | // Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it. 12 | PrimaryActorTick.bCanEverTick = true; 13 | } 14 | 15 | // Called when the game starts or when spawned 16 | void AEditorTickingActors::BeginPlay() 17 | { 18 | Super::BeginPlay(); 19 | 20 | if (ToLiveLinkData && !ToLiveLinkData->WeightsRead) 21 | ToLiveLinkData->WeightsRead = true; 22 | 23 | } 24 | 25 | void AEditorTickingActors::ComputeBlendWeights() 26 | { 27 | 28 | ParallelFor(BlendShapes.Num(), [&](int32 Index) { 29 | 30 | // For now just computing the average distance between the reference pose and the blenshape pose scaled by DistanceInfluence 31 | if (BlendShapes[Index]->UseAsReferencePose) 32 | { 33 | Weights[Index] = 1.f; 34 | return; 35 | } 36 | if (!BlendShapes[Index]->LocationEnabled) 37 | { 38 | Weights[Index] = 0.f; 39 | BlendShapes[Index]->Value = 0.f; 40 | return; 41 | } 42 | 43 | //For a given BlendShape, get the indices of vertices relevant to monitor 44 | TArray& vertices = BlendShapes[Index]->VerticesToControl; 45 | 46 | //For a given BlendShape, get s user define scalar to scale the 47 | float BlendShapeCustomDistanceInfluence = BlendShapes[Index]->DistanceInfluence; 48 | 49 | int NumOfvertices = vertices.Num(); 50 | if (NumOfvertices > 0) 51 | { 52 | float Distance = 0.f; 53 | 54 | for (int i = 0; i < NumOfvertices; i++) 55 | { 56 | //Distance += FMath::Clamp(1.0f - BlendShapeCustomDistanceInfluence * DistanceDependency * (CurrentPose[vertices[i]] - BlendShapes[Index]->VerticesMaxMvt[vertices[i]]).Size() - BlendShapes[Index]->DistanceOffset, 0.f, 1.f); 57 | 58 | FVector Curent_minus_Blendshape = CurrentPose[vertices[i]] - BlendShapes[Index]->VerticesMaxMvt[vertices[i]]; 59 | 60 | FVector Reference_minus_Blendshape = ReferenceBladeShape->VerticesMaxMvt[vertices[i]]- BlendShapes[Index]->VerticesMaxMvt[vertices[i]]; 61 | 62 | float DotP = FMath::Clamp(DistanceDependency*(FVector::DotProduct(Curent_minus_Blendshape, Reference_minus_Blendshape) - BlendShapes[Index]->DistanceOffset*0.001f),0.f,1.f); 63 | 64 | Distance += 1.0f - DotP; 65 | 66 | //Distance += FMath::Clamp(1.0f - BlendShapeCustomDistanceInfluence * DistanceDependency * (CurrentPose[vertices[i]] - BlendShapes[Index]->VerticesMaxMvt[vertices[i]]).Size() - BlendShapes[Index]->DistanceOffset, 0.f, 1.f); 67 | } 68 | 69 | float weight = Distance /= NumOfvertices; 70 | Weights[Index] = weight; 71 | BlendShapes[Index]->Value = weight; 72 | } 73 | 74 | 75 | }); 76 | 77 | } 78 | 79 | // Called every frame 80 | void AEditorTickingActors::Tick(float DeltaTime) 81 | { 82 | Super::Tick(DeltaTime); 83 | 84 | TimeAcuBlendW += DeltaTime; 85 | if (TimeAcuBlendW > 1.f / 30.f) 86 | { 87 | TimeAcuBlendW = 0.f; 88 | 89 | if (ToLiveLinkData && ToLiveLinkData->WeightsRead) 90 | { 91 | 92 | if (CurrentPose.Num() == 468) 93 | { 94 | if (ReferenceBladeShape) 95 | { 96 | 97 | Weights.SetNum(BlendShapes.Num()); 98 | 99 | ComputeBlendWeights(); 100 | 101 | 102 | ToLiveLinkData->BlendShapeMap.Empty(); 103 | 104 | for (int i = 0; i < Weights.Num(); i++) 105 | { 106 | if(!BlendShapes[i]->UseAsReferencePose) 107 | ToLiveLinkData->BlendShapeMap.Add(BlendShapes[i]->Location_Shape, BlendShapes[i]->Value); 108 | } 109 | 110 | 111 | FRotator Head_R_LS = (HeadRotation.Quaternion()*FRotator(0.f,90.f,0.f).Quaternion() * WS_PawnRotation.Quaternion().Inverse()).Inverse().Rotator(); 112 | 113 | 114 | 115 | ToLiveLinkData->BlendShapeMap.Add(EARFaceBlendShape::HeadYaw, Head_R_LS.Yaw/180.f*3.14156535f); 116 | ToLiveLinkData->BlendShapeMap.Add(EARFaceBlendShape::HeadRoll, HeadRotation.Pitch / 180.f * 3.14156535f); 117 | ToLiveLinkData->BlendShapeMap.Add(EARFaceBlendShape::HeadPitch, -HeadRotation.Roll / 180.f * 3.14156535f); 118 | 119 | BlendShapeMap = ToLiveLinkData->BlendShapeMap; 120 | 121 | ToLiveLinkData->BlendWeights = Weights; 122 | 123 | ToLiveLinkData->WeightsRead = false; 124 | 125 | } 126 | else 127 | { 128 | UE_LOG(LogTemp, Warning, TEXT("Reference blenshape Pose not set")); 129 | } 130 | 131 | } 132 | } 133 | } 134 | 135 | 136 | } 137 | 138 | #if WITH_EDITOR 139 | bool AEditorTickingActors::ShouldTickIfViewportsOnly() const 140 | { 141 | return true; 142 | } 143 | #endif 144 | -------------------------------------------------------------------------------- /Source/AndroidFaceCapture/Private/LiveLink/VirtualAndroidARLiveLinkSubject.cpp: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | 4 | #include "LiveLink/VirtualAndroidARLiveLinkSubject.h" 5 | #include "Roles/LiveLinkBasicRole.h" 6 | #include "EditorTickingActors.h" 7 | #include "EngineUtils.h" // for TActorIterator 8 | #include "Roles/LiveLinkAnimationRole.h" 9 | #include "Roles/LiveLinkAnimationTypes.h" 10 | 11 | 12 | 13 | namespace LiveLinkAndAnimationVirtualSubjectUtils 14 | { 15 | void AddToBoneNames(TArray& BoneNames, const TArray& NewBoneNames, const FName Prefix) 16 | { 17 | FString NameFormat; 18 | if (Prefix != NAME_None) 19 | { 20 | NameFormat = Prefix.ToString() + TEXT("_"); 21 | } 22 | 23 | BoneNames.Reserve(BoneNames.Num() + NewBoneNames.Num()); 24 | 25 | for (const FName& NewBoneName : NewBoneNames) 26 | { 27 | BoneNames.Add(*(NameFormat + NewBoneName.ToString())); 28 | } 29 | } 30 | 31 | void AddToBoneParents(TArray& BoneParents, const TArray& NewBoneParents) 32 | { 33 | const int32 Offset = BoneParents.Num(); 34 | 35 | BoneParents.Reserve(BoneParents.Num() + NewBoneParents.Num()); 36 | 37 | for (int32 BoneParent : NewBoneParents) 38 | { 39 | // Here we are combining multiple bone hierarchies under one root bone 40 | // Each hierarchy is complete self contained so we have a simple calculation to perform 41 | // 1) Bones with out a parent get parented to root (-1 => 0 ) 42 | // 2) Bones with a parent need and offset based on the current size of the buffer 43 | if (BoneParent == INDEX_NONE) 44 | { 45 | BoneParents.Add(0); 46 | } 47 | else 48 | { 49 | BoneParents.Add(BoneParent + Offset); 50 | } 51 | } 52 | } 53 | } 54 | 55 | UVirtualAndroidARLiveLinkSubject::UVirtualAndroidARLiveLinkSubject() 56 | { 57 | Role = ULiveLinkBasicRole::StaticClass(); 58 | 59 | } 60 | 61 | void UVirtualAndroidARLiveLinkSubject::Update() 62 | { 63 | Super::Update(); 64 | 65 | TArray ActiveSubjects; 66 | ActiveSubjects.Add(SubjectKey); 67 | 68 | if (!DataSource) 69 | return; 70 | 71 | if (DataSource && !DataSource->WeightsRead) 72 | { 73 | FaceBlendShapes = DataSource->BlendShapeMap; 74 | DataSource->WeightsRead = true; 75 | } 76 | 77 | const UEnum* EnumPtr = StaticEnum(); 78 | if (EnumPtr == nullptr) 79 | { 80 | return; 81 | } 82 | 83 | TArray SubjectSnapshot; 84 | if (BuildSubjectSnapshot(SubjectSnapshot)) 85 | { 86 | 87 | BuildSkeleton(SubjectSnapshot); 88 | BuildFrame(SubjectSnapshot); 89 | } 90 | 91 | } 92 | 93 | 94 | 95 | void UVirtualAndroidARLiveLinkSubject::BuildSkeleton(const TArray& InSubjectSnapshots) 96 | { 97 | 98 | 99 | if (DoesSkeletonNeedRebuilding()) 100 | { 101 | FrameSnapshot.StaticData.InitializeWith(FLiveLinkSkeletonStaticData::StaticStruct(), nullptr); 102 | FLiveLinkSkeletonStaticData* SkeletonData = FrameSnapshot.StaticData.Cast(); 103 | /* 104 | TArray BoneNames{ TEXT("Root") }; 105 | TArray BoneParents{ INDEX_NONE }; 106 | 107 | check(InSubjectSnapshots.Num() == Subjects.Num()); 108 | for (int32 i = 0; i < InSubjectSnapshots.Num(); ++i) 109 | { 110 | const FLiveLinkSubjectFrameData& SubjectSnapShotData = InSubjectSnapshots[i]; 111 | check(SubjectSnapShotData.StaticData.IsValid()); 112 | const FLiveLinkSkeletonStaticData* SubjectSkeletonData = SubjectSnapShotData.StaticData.Cast(); 113 | 114 | const FName BonePrefix = bAppendSubjectNameToBones ? Subjects[i] : NAME_None; 115 | LiveLinkAndAnimationVirtualSubjectUtils::AddToBoneNames(BoneNames, SubjectSkeletonData->GetBoneNames(), BonePrefix); 116 | LiveLinkAndAnimationVirtualSubjectUtils::AddToBoneParents(BoneParents, SubjectSkeletonData->GetBoneParents()); 117 | SkeletonData->PropertyNames.Append(SubjectSkeletonData->PropertyNames); 118 | } 119 | 120 | SkeletonData->SetBoneNames(BoneNames); 121 | SkeletonData->SetBoneParents(BoneParents); 122 | */ 123 | bInvalidate = false; 124 | } 125 | 126 | } 127 | 128 | static FName ParseEnumName(FName EnumName) 129 | { 130 | const int32 BlendShapeEnumNameLength = 19; 131 | FString EnumString = EnumName.ToString(); 132 | return FName(*EnumString.Right(EnumString.Len() - BlendShapeEnumNameLength)); 133 | } 134 | 135 | void UVirtualAndroidARLiveLinkSubject::BuildFrame(const TArray& InSubjectSnapshots) 136 | { 137 | 138 | 139 | if (!FrameSnapshot.FrameData.IsValid()) 140 | { 141 | FrameSnapshot.FrameData.InitializeWith(FLiveLinkAnimationFrameData::StaticStruct(), nullptr); 142 | } 143 | 144 | FLiveLinkSkeletonStaticData* SnapshotSkeletonData = FrameSnapshot.StaticData.Cast(); 145 | FLiveLinkAnimationFrameData* SnapshotFrameData = FrameSnapshot.FrameData.Cast(); 146 | 147 | 148 | //Update property names array 149 | SnapshotSkeletonData->PropertyNames.Reset((int32)EARFaceBlendShape::MAX); 150 | 151 | //BlendShapeData.StaticData.PropertyNames.Reset((int32)EARFaceBlendShape::MAX); 152 | 153 | //Iterate through all valid blend shapes to extract names 154 | const UEnum* EnumPtr = StaticEnum(); 155 | for (int32 Shape = 0; Shape < (int32)EARFaceBlendShape::MAX; Shape++) 156 | { 157 | if (FaceBlendShapes.Contains((EARFaceBlendShape)Shape)) 158 | { 159 | //Blendshapes don't change over time. If they were to change, we would need to keep track 160 | //of previous values to always have frame data matching static data 161 | const FName ShapeName = ParseEnumName(EnumPtr->GetNameByValue(Shape)); 162 | SnapshotSkeletonData->PropertyNames.Add(ShapeName); 163 | } 164 | } 165 | 166 | // Iterate through all of the blend shapes copying them into the LiveLink data type 167 | for (int32 Shape = 0; Shape < (int32)EARFaceBlendShape::MAX; Shape++) 168 | { 169 | if (FaceBlendShapes.Contains((EARFaceBlendShape)Shape)) 170 | { 171 | const float CurveValue = FaceBlendShapes.FindChecked((EARFaceBlendShape)Shape); 172 | SnapshotFrameData->PropertyValues.Add(CurveValue); 173 | 174 | } 175 | } 176 | 177 | 178 | 179 | SnapshotFrameData->Transforms.Reset(SnapshotSkeletonData->GetBoneNames().Num()); 180 | SnapshotFrameData->Transforms.Add(FTransform::Identity); 181 | SnapshotFrameData->MetaData.StringMetaData.Empty(); 182 | 183 | //Go over each subject snapshot and take transforms and curves 184 | check(InSubjectSnapshots.Num() == Subjects.Num()); 185 | for (int32 i = 0; i < InSubjectSnapshots.Num(); ++i) 186 | { 187 | const FLiveLinkSubjectFrameData& SubjectSnapShotData = InSubjectSnapshots[i]; 188 | check(SubjectSnapShotData.FrameData.IsValid()); 189 | const FLiveLinkAnimationFrameData* SubjectFrameData = SubjectSnapShotData.FrameData.Cast(); 190 | 191 | SnapshotFrameData->Transforms.Append(SubjectFrameData->Transforms); 192 | SnapshotFrameData->PropertyValues.Append(SubjectFrameData->PropertyValues); 193 | for (const auto& MetaDatum : SubjectFrameData->MetaData.StringMetaData) 194 | { 195 | const FName QualifiedKey = FName(*(Subjects[i].ToString() + MetaDatum.Key.ToString())); 196 | SnapshotFrameData->MetaData.StringMetaData.Emplace(Subjects[i], MetaDatum.Value); 197 | } 198 | } 199 | 200 | //UE_LOG(LogTemp, Warning, TEXT("BuildFrame")); 201 | } 202 | 203 | bool UVirtualAndroidARLiveLinkSubject::DoesSkeletonNeedRebuilding() const 204 | { 205 | return !FrameSnapshot.StaticData.IsValid() || bInvalidate; 206 | } 207 | 208 | bool UVirtualAndroidARLiveLinkSubject::BuildSubjectSnapshot(TArray& OutSnapshot) 209 | { 210 | //UE_LOG(LogTemp, Warning, TEXT("BuildSubjectSnapshot Subjects.Num() %d"), Subjects.Num()); 211 | 212 | OutSnapshot.Reset(Subjects.Num()); 213 | 214 | bool bSnapshotDone = true; 215 | 216 | for (const FName& SubjectName : Subjects) 217 | { 218 | FLiveLinkSubjectFrameData& NextSnapshot = OutSnapshot.AddDefaulted_GetRef(); 219 | if (!LiveLinkClient->EvaluateFrame_AnyThread(SubjectName, GetRole(), NextSnapshot)) 220 | { 221 | bSnapshotDone = false; 222 | break; 223 | } 224 | } 225 | 226 | return bSnapshotDone; 227 | } -------------------------------------------------------------------------------- /Source/AndroidFaceCapture/Private/TCP_Data_Receiver.cpp: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | 4 | #include "TCP_Data_Receiver.h" 5 | #include "Kismet/KismetStringLibrary.h" 6 | #include "Async/ParallelFor.h" 7 | 8 | void ATCP_Data_Receiver::BeginPlay() 9 | { 10 | Super::BeginPlay(); 11 | 12 | /* 13 | FTcpSocketDisconnectDelegate DisconnectedDelegate; 14 | FTcpSocketConnectDelegate ConnectedDelegate; 15 | FTcpSocketReceivedMessageDelegate MessageReceivedDelegate; 16 | */ 17 | DisconnectedDelegate.BindDynamic(this, &ATCP_Data_Receiver::DisconnectionD); //.BindDynamic(&DisconnectionD); 18 | ConnectedDelegate.BindDynamic(this, &ATCP_Data_Receiver::ConnectionD); // .BindRaw(&ConnectionD); 19 | MessageReceivedDelegate.BindDynamic(this, &ATCP_Data_Receiver::MessageReceptionD); 20 | 21 | Connect(IPAdress, Port, DisconnectedDelegate, ConnectedDelegate, MessageReceivedDelegate, Connect_ID); 22 | } 23 | 24 | void ATCP_Data_Receiver::Tick(float DeltaTime) 25 | { 26 | Super::Tick(DeltaTime); 27 | 28 | AcuTime += DeltaTime; 29 | 30 | if (AcuTime > 1.f) 31 | { 32 | AcuTime = 0.f; 33 | 34 | UE_LOG(LogTemp, Warning, TEXT("receivedcount %d receivedLatentcount %d"), receivedcount, receivedLatentcount); 35 | receivedcount = 0; 36 | receivedLatentcount = 0; 37 | } 38 | 39 | if (!Connected) 40 | { 41 | ReconnectTryAcu += DeltaTime; 42 | 43 | if (ReconnectTryAcu > 1.f) 44 | { 45 | ReconnectTryAcu = 0.f; 46 | Connect(IPAdress, Port, DisconnectedDelegate, ConnectedDelegate, MessageReceivedDelegate, Connect_ID); 47 | } 48 | } 49 | 50 | 51 | } 52 | 53 | void ATCP_Data_Receiver::DisconnectionD(int32 ID) 54 | { 55 | Connected = false; 56 | } 57 | 58 | void ATCP_Data_Receiver::ConnectionD(int32 ID) 59 | { 60 | Connected = true; 61 | } 62 | 63 | void ATCP_Data_Receiver::Message_ReadVectorArray(TArray& Message, TArray& Out, FMatrix& CenterFaceMat) 64 | { 65 | 66 | int Offset = 0; 67 | while (Offset <= Message.Num() - 12 - 64) 68 | { 69 | float X, Y, Z; 70 | unsigned char byteArray[4]; 71 | 72 | for (int i = 0; i < 4; i++) 73 | { 74 | byteArray[i] = Message[3 - i + Offset]; 75 | } 76 | 77 | FMemory::Memcpy(&X, byteArray, 4); 78 | 79 | for (int i = 0; i < 4; i++) 80 | { 81 | byteArray[i] = Message[3 - i + 4 + Offset]; 82 | } 83 | 84 | FMemory::Memcpy(&Y, byteArray, 4); 85 | 86 | for (int i = 0; i < 4; i++) 87 | { 88 | byteArray[i] = Message[3 - i + 8 + Offset]; 89 | } 90 | 91 | FMemory::Memcpy(&Z, byteArray, 4); 92 | 93 | Out.Add(FVector(X, Y, Z)); 94 | 95 | Offset = Offset + 12; 96 | } 97 | 98 | //The last 16 float describe a columnMajor matrix for the center of the face 99 | //UE_LOG(LogTemp, Warning, TEXT("remaining floats %d"), Message.Num() - Offset); 100 | 101 | TArray MatrixFloatsColumnFirst; 102 | 103 | for (int i = 0; i < 16; i++) 104 | { 105 | float X; 106 | unsigned char byteArray[4]; 107 | 108 | for (int j = 0; j < 4; j++) 109 | { 110 | byteArray[j] = Message[3 - j + Offset]; 111 | } 112 | FMemory::Memcpy(&X, byteArray, 4); 113 | 114 | Offset = Offset + 4; 115 | 116 | MatrixFloatsColumnFirst.Add(X); 117 | } 118 | 119 | // M[row][Column] and MatrixFloatsColumnFirst is 16 floats Column first [C1_1][C1_2][C1_33]... 120 | CenterFaceMat = FMatrix::Identity; 121 | 122 | FString DebugMat = ""; 123 | 124 | for (int i = 0; i < 4; i++) 125 | { 126 | for (int j = 0; j < 4; j++) 127 | { 128 | int index = i * 4 + j; 129 | 130 | CenterFaceMat.M[j][i] = MatrixFloatsColumnFirst[index]; 131 | 132 | //DebugMat += "M.[" + FString::SanitizeFloat(j) + "][" + FString::SanitizeFloat(i)+"] = " + FString::SanitizeFloat(MatrixFloatsColumnFirst[index])+ (j==3? "\n" :" "); 133 | } 134 | } 135 | 136 | //UE_LOG(LogTemp, Warning, TEXT("DebugMat = \n %s"), *DebugMat); 137 | 138 | } 139 | 140 | void ATCP_Data_Receiver::MessageReceptionD(int32 ID, TArray& Msg) 141 | { 142 | 143 | if (Msg.Num() == 0) 144 | return; 145 | 146 | FMatrix CenterFace; 147 | 148 | FTransform CenterFaceT; 149 | CenterFaceT.SetLocation(FVector(0.f, 0.f, 0.f)); 150 | CenterFaceT.SetScale3D(FVector(1.f, 1.f, 1.f)); 151 | CenterFaceT.SetRotation(FQuat::Identity); 152 | 153 | 154 | if (Msg.Num() == 5680) 155 | { 156 | LatentSet = false; 157 | LatentCopy.Empty(); 158 | 159 | TArray Data_Vector; 160 | Message_ReadVectorArray(Msg, Data_Vector, CenterFace); 161 | 162 | if (EnableHeadTransformData) 163 | { 164 | CenterFaceT.SetLocation(CenterFace.TransformPosition(FVector(0.f, 0.f, 0.f))); 165 | CenterFaceT.SetRotation(CenterFace.Rotator().Quaternion()); 166 | } 167 | 168 | if (SetData.IsBound()) 169 | SetData.Broadcast(Data_Vector, CenterFaceT); 170 | receivedcount++; 171 | 172 | return; 173 | } 174 | 175 | 176 | //UE_LOG(LogTemp, Warning, TEXT("Message length %d latent length %d"), Msg.Num(), LatentCopy.Num()); 177 | 178 | if (!LatentSet) 179 | { 180 | while (Msg.Num() >= 5680) 181 | { 182 | LatentSet = false; 183 | LatentCopy.Empty(); 184 | 185 | TArray DummyTemp; 186 | //Message_ReadBytes(5616, Msg, DummyTemp); 187 | 188 | for (int i = 0; i < 5680; i++) 189 | { 190 | DummyTemp.Add(Message_ReadByte(Msg)); 191 | } 192 | 193 | TArray Data_Vector; 194 | Message_ReadVectorArray(DummyTemp, Data_Vector, CenterFace); 195 | 196 | if (EnableHeadTransformData) 197 | { 198 | CenterFaceT.SetLocation(CenterFace.TransformPosition(FVector(0.f, 0.f, 0.f))); 199 | CenterFaceT.SetRotation(CenterFace.Rotator().Quaternion()); 200 | } 201 | 202 | 203 | if (SetData.IsBound()) 204 | SetData.Broadcast(Data_Vector, CenterFaceT); 205 | 206 | receivedcount++; 207 | } 208 | } 209 | 210 | 211 | if (LatentSet) 212 | { 213 | if ((LatentCopy.Num() + Msg.Num()) % 5680 == 0) 214 | { 215 | LatentSet = false; 216 | LatentCopy.Append(Msg); 217 | 218 | while (LatentCopy.Num() >= 5680) 219 | { 220 | 221 | TArray DummyTemp; 222 | //Message_ReadBytes(5616, Msg, DummyTemp); 223 | 224 | for (int i = 0; i < 5680; i++) 225 | { 226 | DummyTemp.Add(Message_ReadByte(LatentCopy)); 227 | } 228 | 229 | TArray Data_Vector; 230 | Message_ReadVectorArray(DummyTemp, Data_Vector, CenterFace); 231 | 232 | if (EnableHeadTransformData) 233 | { 234 | CenterFaceT.SetLocation(CenterFace.TransformPosition(FVector(0.f, 0.f, 0.f))); 235 | CenterFaceT.SetRotation(CenterFace.Rotator().Quaternion()); 236 | } 237 | 238 | if (SetData.IsBound()) 239 | SetData.Broadcast(Data_Vector, CenterFaceT); 240 | 241 | receivedcount++; 242 | receivedLatentcount++; 243 | } 244 | 245 | LatentCopy.Empty(); 246 | 247 | } 248 | } 249 | else 250 | { 251 | LatentCopy = Msg; 252 | LatentSet = true; 253 | } 254 | 255 | } 256 | 257 | void ATCP_Data_Receiver::SetVectorData_Implementation(TArray& Data) 258 | { 259 | 260 | } 261 | -------------------------------------------------------------------------------- /Source/AndroidFaceCapture/Public/AndroidBlenshape.h: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "UObject/NoExportTypes.h" 7 | #include "HAL/ThreadSafeBool.h" 8 | #include "ARTrackable.h" 9 | #include "AndroidBlenshape.generated.h" 10 | 11 | /** 12 | * 13 | */ 14 | UCLASS(Blueprintable, BlueprintType) 15 | class ANDROIDFACECAPTURE_API UAndroidBlenshape : public UObject 16 | { 17 | GENERATED_BODY() 18 | 19 | public: 20 | 21 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Default") 22 | bool LocationEnabled; 23 | 24 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Default") 25 | EARFaceBlendShape Location_Shape; 26 | 27 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Default") 28 | bool UseAsReferencePose; 29 | 30 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Default") 31 | FString Location; 32 | 33 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Default") 34 | float Value=0.f; 35 | 36 | float GetBlendShapeValue() { return Value; }; 37 | 38 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Default") 39 | float DistanceInfluence = 1.f; 40 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Default") 41 | float DistanceOffset = 0.f; 42 | 43 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Default") 44 | TArray VerticesToControl; 45 | 46 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Default") 47 | TArray VerticesMaxMvt; 48 | 49 | }; 50 | 51 | 52 | /* Currently, data is received via TCP in an Actor set in the world (free TCP socket plugin), this actor convert the incoming byte array to the valuable vertices position and head transform. 53 | * Another actor process this information to compute the blendweights by comparing incoming data to predefined blendshape references (another tool/actor is in the world to define a subset of vertices relevant for a given blenshape) 54 | * BlendWeights are stored in a UAndroidBlenshapeWeights and WeightsRead is set to false 55 | * Once the livelink subject is updated, it read the blendweights from UAndroidBlenshapeWeights, unlocked it by setting WeightsRead to true, informs the blenshapes in a similar fashion than ARKit does 56 | Alternative would be to convert the TCP plugin to work with UObject instead of actors and do everything as a livelink source subject, including the blend weight computation. Currently i'm computing the blend weights at runtime in an Actor. 57 | Or disregarding Livelink alltogether and figuring out how to send the blendshapes to the animBP directly. 58 | */ 59 | UCLASS(/*Blueprintable, BlueprintType*/ ) 60 | class ANDROIDFACECAPTURE_API UAndroidBlenshapeWeights : public UObject 61 | { 62 | GENERATED_BODY() 63 | 64 | public: 65 | 66 | /* Weights are ordered as in EARFaceBlendShape*/ 67 | //UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Default") 68 | TArray BlendWeights; 69 | 70 | FARBlendShapeMap BlendShapeMap; 71 | 72 | FThreadSafeBool WeightsRead; 73 | 74 | }; 75 | -------------------------------------------------------------------------------- /Source/AndroidFaceCapture/Public/EditorTickingActors.h: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "GameFramework/Actor.h" 7 | #include "AndroidBlenshape.h" 8 | #include "EditorTickingActors.generated.h" 9 | 10 | class UAndroidBlenshapeWeights; 11 | UCLASS() 12 | class ANDROIDFACECAPTURE_API AEditorTickingActors : public AActor 13 | { 14 | GENERATED_BODY() 15 | 16 | public: 17 | // Sets default values for this actor's properties 18 | AEditorTickingActors(); 19 | 20 | protected: 21 | // Called when the game starts or when spawned 22 | virtual void BeginPlay() override; 23 | 24 | void ComputeBlendWeights(); 25 | 26 | public: 27 | // Called every frame 28 | virtual void Tick(float DeltaTime) override; 29 | 30 | 31 | 32 | #if WITH_EDITOR 33 | 34 | bool ShouldTickIfViewportsOnly() const override; 35 | 36 | #endif 37 | 38 | UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Default") 39 | bool SelectReferenceLocation; 40 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Default") 41 | EARFaceBlendShape Selected_Location; 42 | 43 | UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Default") 44 | TArray Weights; 45 | 46 | UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Default") 47 | float DistanceDependency=100.f; 48 | 49 | UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Default") 50 | TArray CurrentPose; 51 | 52 | UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Default") 53 | FRotator HeadRotation; 54 | UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Default") 55 | FRotator WS_PawnRotation=FRotator(0.f,90.f,0.f); 56 | 57 | UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Default") 58 | UAndroidBlenshape* ReferenceBladeShape; 59 | 60 | UPROPERTY(BlueprintReadWrite,EditAnywhere,Category="Default") 61 | TArrayBlendShapes; 62 | 63 | UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Default") 64 | UAndroidBlenshapeWeights* ToLiveLinkData; 65 | 66 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Default") 67 | TMap BlendShapeMap; 68 | 69 | private: 70 | 71 | float TimeAcuBlendW = 0.f; 72 | 73 | }; 74 | -------------------------------------------------------------------------------- /Source/AndroidFaceCapture/Public/LiveLink/VirtualAndroidARLiveLinkSubject.h: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "LiveLinkVirtualSubject.h" 7 | #include "ILiveLinkClient.h" 8 | #include "HAL/ThreadSafeBool.h" 9 | #include "ARTrackable.h" 10 | #include "Roles/LiveLinkAnimationTypes.h" 11 | #include "LiveLinkAnimationVirtualSubject.h" 12 | #include "VirtualSubjects/LiveLinkBlueprintVirtualSubject.h" 13 | #include "VirtualAndroidARLiveLinkSubject.generated.h" 14 | 15 | class AEditorTickingActors; 16 | class UAndroidBlenshapeWeights; 17 | /** 18 | * 19 | */ 20 | UCLASS(Blueprintable, meta = (DisplayName = "Android FaceData Virtual Subject")) 21 | class ANDROIDFACECAPTURE_API UVirtualAndroidARLiveLinkSubject : public ULiveLinkVirtualSubject 22 | { 23 | GENERATED_BODY() 24 | 25 | 26 | public: 27 | UVirtualAndroidARLiveLinkSubject(); 28 | 29 | virtual void Update() override; 30 | 31 | UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Default") 32 | UAndroidBlenshapeWeights* DataSource; 33 | 34 | FARBlendShapeMap FaceBlendShapes; 35 | 36 | // Builds a new ref skeleton based on the current subject state (can early out if ref skeleton is already up to date) 37 | void BuildSkeleton(const TArray& InSubjectSnapshots); 38 | 39 | void BuildFrame(const TArray& InSubjectSnapshots); 40 | 41 | // Tests to see if current ref skeleton is up to data 42 | bool DoesSkeletonNeedRebuilding() const; 43 | bool bInvalidate; 44 | 45 | 46 | protected: 47 | 48 | bool BuildSubjectSnapshot(TArray& OutSnapshot); 49 | 50 | public: 51 | /* 52 | //Whether to append SubjectName to each bones part of the virtual hierarchy 53 | UPROPERTY(EditAnywhere, Category = "Settings") 54 | bool bAppendSubjectNameToBones; 55 | */ 56 | }; 57 | -------------------------------------------------------------------------------- /Source/AndroidFaceCapture/Public/TCP_Data_Receiver.h: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "TcpSocketConnection.h" 7 | #include "TCP_Data_Receiver.generated.h" 8 | 9 | DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FTcpVectorDataDelegate, const TArray&, VectorData, const FTransform&, CenterFaceT); 10 | 11 | /** 12 | * 13 | */ 14 | UCLASS() 15 | class ANDROIDFACECAPTURE_API ATCP_Data_Receiver : public ATcpSocketConnection 16 | { 17 | GENERATED_BODY() 18 | 19 | 20 | protected: 21 | // Called when the game starts or when spawned 22 | virtual void BeginPlay() override; 23 | virtual void Tick(float DeltaTime) override; 24 | 25 | public: 26 | 27 | UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Default") 28 | FString IPAdress; 29 | UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Default") 30 | int Port; 31 | 32 | UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Default") 33 | bool EnableHeadTransformData; 34 | 35 | UPROPERTY(BlueprintReadOnly, Category = "Default") 36 | int Connect_ID; 37 | 38 | UPROPERTY(Transient) 39 | int bytesOfDataPacket = 0; 40 | UPROPERTY(Transient) 41 | int bytesOfHeaderPacket = 5; 42 | 43 | UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Data") 44 | void SetVectorData(TArray& Data); 45 | 46 | UFUNCTION() 47 | void DisconnectionD(int32 ID); 48 | UFUNCTION() 49 | void ConnectionD(int32 ID); 50 | 51 | void Message_ReadVectorArray(TArray& Message, TArray& Out, FMatrix& CenterFaceMat); 52 | UFUNCTION() 53 | void MessageReceptionD(int32 ID, TArray& Msg); 54 | 55 | UPROPERTY(BlueprintAssignable) 56 | FTcpVectorDataDelegate SetData; 57 | 58 | private: 59 | 60 | float AcuTime = 0.f; 61 | int receivedcount = 0; 62 | int receivedLatentcount = 0; 63 | 64 | bool Connected = false; 65 | float ReconnectTryAcu = 0.f; 66 | 67 | FTcpSocketDisconnectDelegate DisconnectedDelegate; 68 | FTcpSocketConnectDelegate ConnectedDelegate; 69 | FTcpSocketReceivedMessageDelegate MessageReceivedDelegate; 70 | 71 | TArray LatentCopy; 72 | bool LatentSet = false; 73 | 74 | 75 | 76 | }; 77 | -------------------------------------------------------------------------------- /Source/AndroidFaceCaptureEditor.Target.cs: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | using UnrealBuildTool; 4 | using System.Collections.Generic; 5 | 6 | public class AndroidFaceCaptureEditorTarget : TargetRules 7 | { 8 | public AndroidFaceCaptureEditorTarget( TargetInfo Target) : base(Target) 9 | { 10 | Type = TargetType.Editor; 11 | DefaultBuildSettings = BuildSettingsVersion.V2; 12 | ExtraModuleNames.AddRange( new string[] { "AndroidFaceCapture","AndroidFaceCaptureEditor" } ); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Source/AndroidFaceCaptureEditor/AndroidBlenshapeAssetTypeActions.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "AndroidBlenshapeAssetTypeActions.h" 3 | #include "AssetTypeCategories.h" 4 | #include "Engine/EngineTypes.h" 5 | #include "Modules/ModuleManager.h" 6 | #include "AndroidBlenshape.h" 7 | #include "Internationalization/Internationalization.h" 8 | 9 | #define LOCTEXT_NAMESPACE "AndroidBlenshape" 10 | 11 | 12 | FText FAndroidBlenshapeAssetTypeActions::GetName() const 13 | { 14 | return LOCTEXT("FAndroidBlenshapeAssetTypeActionsName", "AndroidBlenshape"); 15 | } 16 | 17 | FColor FAndroidBlenshapeAssetTypeActions::GetTypeColor() const 18 | { 19 | return FColor::Cyan; 20 | } 21 | 22 | UClass* FAndroidBlenshapeAssetTypeActions::GetSupportedClass() const 23 | { 24 | return UAndroidBlenshape::StaticClass(); 25 | } 26 | 27 | uint32 FAndroidBlenshapeAssetTypeActions::GetCategories() 28 | { 29 | return EAssetTypeCategories::Misc | MyAssetCategory; 30 | } 31 | 32 | #undef LOCTEXT_NAMESPACE 33 | 34 | #define LOCTEXT_NAMESPACE "AndroidBlenshapeWeights" 35 | 36 | 37 | FText FAndroidBlenshapeWeightsAssetTypeActions::GetName() const 38 | { 39 | return LOCTEXT("FAndroidBlenshapeWeightsAssetTypeActionsName", "AndroidBlenshapeWeights"); 40 | } 41 | 42 | FColor FAndroidBlenshapeWeightsAssetTypeActions::GetTypeColor() const 43 | { 44 | return FColor::Cyan; 45 | } 46 | 47 | UClass* FAndroidBlenshapeWeightsAssetTypeActions::GetSupportedClass() const 48 | { 49 | return UAndroidBlenshapeWeights::StaticClass(); 50 | } 51 | 52 | uint32 FAndroidBlenshapeWeightsAssetTypeActions::GetCategories() 53 | { 54 | return EAssetTypeCategories::Misc | MyAssetCategory; 55 | } 56 | 57 | #undef LOCTEXT_NAMESPACE 58 | /* 59 | #define LOCTEXT_NAMESPACE "PlanetSpawnableMesh" 60 | 61 | 62 | FText FPlanetSpawnableMeshAssetTypeActions::GetName() const 63 | { 64 | return LOCTEXT("FPlanetSpawnableMeshAssetTypeActionsName", "PlanetSpawnableMesh"); 65 | } 66 | 67 | FColor FPlanetSpawnableMeshAssetTypeActions::GetTypeColor() const 68 | { 69 | return FColor::Cyan; 70 | } 71 | 72 | UClass* FPlanetSpawnableMeshAssetTypeActions::GetSupportedClass() const 73 | { 74 | return UPlanetSpawnableMesh::StaticClass(); 75 | } 76 | 77 | uint32 FPlanetSpawnableMeshAssetTypeActions::GetCategories() 78 | { 79 | return EAssetTypeCategories::Misc | MyAssetCategory; 80 | } 81 | 82 | #undef LOCTEXT_NAMESPACE 83 | 84 | #define LOCTEXT_NAMESPACE "PlanetGroundMaterial" 85 | 86 | 87 | FText FPlanetGroundMaterialAssetTypeActions::GetName() const 88 | { 89 | return LOCTEXT("FPlanetGroundMaterialAssetTypeActionsName", "PlanetGroundMaterial"); 90 | } 91 | 92 | FColor FPlanetGroundMaterialAssetTypeActions::GetTypeColor() const 93 | { 94 | return FColor::Cyan; 95 | } 96 | 97 | UClass* FPlanetGroundMaterialAssetTypeActions::GetSupportedClass() const 98 | { 99 | return UPlanetGroundMaterial::StaticClass(); 100 | } 101 | 102 | uint32 FPlanetGroundMaterialAssetTypeActions::GetCategories() 103 | { 104 | return EAssetTypeCategories::Misc | MyAssetCategory; 105 | } 106 | 107 | #undef LOCTEXT_NAMESPACE 108 | 109 | 110 | 111 | 112 | #define LOCTEXT_NAMESPACE "PlanetStaticEcoData" 113 | 114 | 115 | FText FPlanetStaticEcoDataAssetTypeActions::GetName() const 116 | { 117 | return LOCTEXT("FPlanetStaticEcoDataAssetTypeActionsName", "PlanetStaticEcoData"); 118 | } 119 | 120 | FColor FPlanetStaticEcoDataAssetTypeActions::GetTypeColor() const 121 | { 122 | return FColor::Cyan; 123 | } 124 | 125 | UClass* FPlanetStaticEcoDataAssetTypeActions::GetSupportedClass() const 126 | { 127 | return UPlanetStaticEcoData::StaticClass(); 128 | } 129 | 130 | uint32 FPlanetStaticEcoDataAssetTypeActions::GetCategories() 131 | { 132 | return EAssetTypeCategories::Misc | MyAssetCategory; 133 | } 134 | 135 | #undef LOCTEXT_NAMESPACE 136 | */ -------------------------------------------------------------------------------- /Source/AndroidFaceCaptureEditor/AndroidBlenshapeAssetTypeActions.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | 4 | #include "CoreMinimal.h" 5 | #include "Toolkits/IToolkitHost.h" 6 | #include "AssetTypeActions_Base.h" 7 | 8 | class UAndroidBlenshape; 9 | 10 | class FAndroidBlenshapeAssetTypeActions : public FAssetTypeActions_Base 11 | { 12 | public: 13 | //FEcoSystemAssetTypeActions(EAssetTypeCategories::Type InAssetCategory); 14 | 15 | virtual FText GetName() const override; 16 | virtual FColor GetTypeColor() const override; 17 | virtual UClass* GetSupportedClass() const override; 18 | virtual uint32 GetCategories() override; 19 | 20 | private: 21 | EAssetTypeCategories::Type MyAssetCategory; 22 | }; 23 | 24 | class FAndroidBlenshapeWeightsAssetTypeActions : public FAssetTypeActions_Base 25 | { 26 | public: 27 | //FEcoSystemAssetTypeActions(EAssetTypeCategories::Type InAssetCategory); 28 | 29 | virtual FText GetName() const override; 30 | virtual FColor GetTypeColor() const override; 31 | virtual UClass* GetSupportedClass() const override; 32 | virtual uint32 GetCategories() override; 33 | 34 | private: 35 | EAssetTypeCategories::Type MyAssetCategory; 36 | }; 37 | /* 38 | class UEcoSystem; 39 | 40 | 41 | class FEcoSystemAssetTypeActions : public FAssetTypeActions_Base 42 | { 43 | public: 44 | //FEcoSystemAssetTypeActions(EAssetTypeCategories::Type InAssetCategory); 45 | 46 | virtual FText GetName() const override; 47 | virtual FColor GetTypeColor() const override; 48 | virtual UClass* GetSupportedClass() const override; 49 | virtual uint32 GetCategories() override; 50 | 51 | private: 52 | EAssetTypeCategories::Type MyAssetCategory; 53 | }; 54 | 55 | class FPlanetSpawnableMeshAssetTypeActions : public FAssetTypeActions_Base 56 | { 57 | public: 58 | //FEcoSystemAssetTypeActions(EAssetTypeCategories::Type InAssetCategory); 59 | 60 | virtual FText GetName() const override; 61 | virtual FColor GetTypeColor() const override; 62 | virtual UClass* GetSupportedClass() const override; 63 | virtual uint32 GetCategories() override; 64 | 65 | private: 66 | EAssetTypeCategories::Type MyAssetCategory; 67 | }; 68 | 69 | class FPlanetGroundMaterialAssetTypeActions : public FAssetTypeActions_Base 70 | { 71 | public: 72 | //FEcoSystemAssetTypeActions(EAssetTypeCategories::Type InAssetCategory); 73 | 74 | virtual FText GetName() const override; 75 | virtual FColor GetTypeColor() const override; 76 | virtual UClass* GetSupportedClass() const override; 77 | virtual uint32 GetCategories() override; 78 | 79 | private: 80 | EAssetTypeCategories::Type MyAssetCategory; 81 | }; 82 | 83 | class FPlanetStaticEcoDataAssetTypeActions : public FAssetTypeActions_Base 84 | { 85 | public: 86 | //FEcoSystemAssetTypeActions(EAssetTypeCategories::Type InAssetCategory); 87 | 88 | virtual FText GetName() const override; 89 | virtual FColor GetTypeColor() const override; 90 | virtual UClass* GetSupportedClass() const override; 91 | virtual uint32 GetCategories() override; 92 | 93 | private: 94 | EAssetTypeCategories::Type MyAssetCategory; 95 | };*/ -------------------------------------------------------------------------------- /Source/AndroidFaceCaptureEditor/AndroidBlenshapeFactory.cpp: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | 4 | #include "AndroidBlenshapeFactory.h" 5 | #include "AndroidFaceCaptureEditor.h" 6 | //The asset header file that we wish to create 7 | //#include "UEcoSystem.h" 8 | //The asset type categories will let us access the various asset categories inside the Editor 9 | #include "AssetTypeCategories.h" 10 | 11 | #define LOCTEXT_NAMESPACE "AndroidBlenshapeFactory" 12 | 13 | UAndroidBlendFactory::UAndroidBlendFactory(const FObjectInitializer & ObjectInitializer) 14 | : Super(ObjectInitializer) 15 | { 16 | bCreateNew = true; 17 | bEditAfterNew = true; 18 | SupportedClass = UAndroidBlenshape::StaticClass(); 19 | } 20 | 21 | 22 | uint32 UAndroidBlendFactory::GetMenuCategories() const 23 | { 24 | //Let's place this asset in the Blueprints category in the Editor 25 | return FAndroidFaceCaptureEditor::GetAssetCategory(); 26 | } 27 | 28 | UObject* UAndroidBlendFactory::FactoryCreateNew(UClass* InClass, UObject* InParent, FName InName, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn) 29 | { 30 | //Create the editor asset 31 | UAndroidBlenshape* OrfeasEditorAsset = NewObject(InParent, InClass, InName, Flags); 32 | return OrfeasEditorAsset; 33 | } 34 | 35 | #undef LOCTEXT_NAMESPACE 36 | 37 | 38 | 39 | #define LOCTEXT_NAMESPACE "AndroidBlenshapeWeightsFactory" 40 | 41 | UAndroidBlenshapeWeightsFactory::UAndroidBlenshapeWeightsFactory(const FObjectInitializer& ObjectInitializer) 42 | : Super(ObjectInitializer) 43 | { 44 | bCreateNew = true; 45 | bEditAfterNew = true; 46 | SupportedClass = UAndroidBlenshapeWeights::StaticClass(); 47 | } 48 | 49 | 50 | uint32 UAndroidBlenshapeWeightsFactory::GetMenuCategories() const 51 | { 52 | //Let's place this asset in the Blueprints category in the Editor 53 | return FAndroidFaceCaptureEditor::GetAssetCategory(); 54 | } 55 | 56 | UObject* UAndroidBlenshapeWeightsFactory::FactoryCreateNew(UClass* InClass, UObject* InParent, FName InName, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn) 57 | { 58 | //Create the editor asset 59 | UAndroidBlenshapeWeights* OrfeasEditorAsset = NewObject(InParent, InClass, InName, Flags); 60 | return OrfeasEditorAsset; 61 | } 62 | 63 | #undef LOCTEXT_NAMESPACE 64 | -------------------------------------------------------------------------------- /Source/AndroidFaceCaptureEditor/AndroidBlenshapeFactory.h: -------------------------------------------------------------------------------- 1 | // Fill out your copyright notice in the Description page of Project Settings. 2 | 3 | #pragma once 4 | 5 | 6 | #include "CoreMinimal.h" 7 | #include "UObject/ObjectMacros.h" 8 | 9 | #include "Factories/Factory.h" 10 | #include "AndroidBlenshape.h" 11 | #include "AndroidBlenshapeFactory.generated.h" 12 | 13 | 14 | 15 | 16 | UCLASS() 17 | class ANDROIDFACECAPTUREEDITOR_API UAndroidBlendFactory : public UFactory 18 | { 19 | GENERATED_UCLASS_BODY() 20 | 21 | public: 22 | 23 | 24 | virtual uint32 GetMenuCategories() const override; 25 | 26 | 27 | 28 | virtual UObject* FactoryCreateNew(UClass* InClass, UObject* InParent, FName InName, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn) override; 29 | 30 | 31 | }; 32 | 33 | 34 | UCLASS() 35 | class ANDROIDFACECAPTUREEDITOR_API UAndroidBlenshapeWeightsFactory : public UFactory 36 | { 37 | GENERATED_UCLASS_BODY() 38 | 39 | public: 40 | 41 | 42 | virtual uint32 GetMenuCategories() const override; 43 | 44 | 45 | 46 | virtual UObject* FactoryCreateNew(UClass* InClass, UObject* InParent, FName InName, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn) override; 47 | 48 | 49 | }; 50 | 51 | 52 | -------------------------------------------------------------------------------- /Source/AndroidFaceCaptureEditor/AndroidFaceCaptureEditor.Build.cs: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | using System; 4 | using System.IO; 5 | using UnrealBuildTool; 6 | 7 | public class AndroidFaceCaptureEditor : ModuleRules 8 | { 9 | public AndroidFaceCaptureEditor(ReadOnlyTargetRules Target) : base(Target) 10 | { 11 | PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; 12 | 13 | 14 | 15 | PublicDependencyModuleNames.AddRange( 16 | new string[] 17 | { 18 | 19 | "Core", 20 | "CoreUObject", 21 | "AndroidFaceCapture", 22 | "UnrealEd", // for FAssetEditorManager 23 | } 24 | ); 25 | 26 | PrivateDependencyModuleNames.AddRange( 27 | new string[] 28 | { 29 | // "ImageWriteQueue", 30 | // "PhysicsCore", 31 | // "RenderCore", 32 | "SlateCore", 33 | "Projects", 34 | "EditorStyle", 35 | } 36 | ); 37 | 38 | } 39 | } 40 | 41 | -------------------------------------------------------------------------------- /Source/AndroidFaceCaptureEditor/AndroidFaceCaptureEditor.cpp: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | #include "AndroidFaceCaptureEditor.h" 4 | //#include "Interfaces/IPluginManager.h" 5 | #include "Misc/Paths.h" 6 | 7 | #include "AndroidBlenshapeAssetTypeActions.h" 8 | #include "Internationalization/Internationalization.h" 9 | 10 | 11 | 12 | IMPLEMENT_PRIMARY_GAME_MODULE(FAndroidFaceCaptureEditor, AndroidFaceCaptureEditor, "AndroidFaceCaptureEditor" ); 13 | 14 | #define LOCTEXT_NAMESPACE "AndroidBlenshape" 15 | 16 | EAssetTypeCategories::Type FAndroidFaceCaptureEditor::FaceAndroidAssetCategory; 17 | 18 | void FAndroidFaceCaptureEditor::StartupModule() 19 | { 20 | 21 | // Only register once 22 | if (!StyleSet.IsValid()) 23 | { 24 | StyleSet = MakeShareable(new FSlateStyleSet("FaceAndroidStyle")); 25 | 26 | FString ContentDir = FPaths::Combine(FPaths::ProjectDir(), TEXT("Resources")); 27 | StyleSet->SetContentRoot(ContentDir); 28 | 29 | FSlateImageBrush* IconBrush = new FSlateImageBrush(StyleSet->RootToContentDir(TEXT("face-scan_16"), TEXT(".png")), FVector2D(16.f, 16.f)); 30 | FSlateImageBrush* ThumbnailBrush = new FSlateImageBrush(StyleSet->RootToContentDir(TEXT("face-scan_128"), TEXT(".png")), FVector2D(128.f, 128.f)); 31 | 32 | if (IconBrush) 33 | StyleSet->Set("ClassIcon.AndroidBlenshape", IconBrush); 34 | if (ThumbnailBrush) 35 | StyleSet->Set("ClassThumbnail.AndroidBlenshape", ThumbnailBrush); 36 | 37 | FSlateImageBrush* IconBrush_mesh = new FSlateImageBrush(StyleSet->RootToContentDir(TEXT("face-scan2_16"), TEXT(".png")), FVector2D(16.f, 16.f)); 38 | FSlateImageBrush* ThumbnailBrush_mesh = new FSlateImageBrush(StyleSet->RootToContentDir(TEXT("face-scan2_128"), TEXT(".png")), FVector2D(128.f, 128.f)); 39 | 40 | 41 | if (IconBrush_mesh) 42 | StyleSet->Set("ClassIcon.AndroidBlenshapeWeights", IconBrush_mesh); 43 | if (ThumbnailBrush_mesh) 44 | StyleSet->Set("ClassThumbnail.AndroidBlenshapeWeights", ThumbnailBrush_mesh); 45 | /* 46 | //Create a brush from the icon 47 | 48 | 49 | 50 | 51 | FSlateImageBrush* IconBrush_mat = new FSlateImageBrush(StyleSet->RootToContentDir(TEXT("Icon16_mat"), TEXT(".png")), FVector2D(16.f, 16.f)); 52 | FSlateImageBrush* ThumbnailBrush_mat = new FSlateImageBrush(StyleSet->RootToContentDir(TEXT("Icon128_mat"), TEXT(".png")), FVector2D(128.f, 128.f)); 53 | 54 | if (IconBrush_mat) 55 | StyleSet->Set("ClassIcon.PlanetGroundMaterial", IconBrush_mat); 56 | if (ThumbnailBrush_mat) 57 | StyleSet->Set("ClassThumbnail.PlanetGroundMaterial", ThumbnailBrush_mat); 58 | 59 | FSlateImageBrush* IconBrush_PData = new FSlateImageBrush(StyleSet->RootToContentDir(TEXT("Icon16_Pdata"), TEXT(".png")), FVector2D(16.f, 16.f)); 60 | FSlateImageBrush* ThumbnailBrush_PData = new FSlateImageBrush(StyleSet->RootToContentDir(TEXT("Icon128_Pdata"), TEXT(".png")), FVector2D(128.f, 128.f)); 61 | 62 | if (IconBrush_PData) 63 | StyleSet->Set("ClassIcon.PlanetStaticEcoData", IconBrush_PData); 64 | if (ThumbnailBrush_PData) 65 | StyleSet->Set("ClassThumbnail.PlanetStaticEcoData", ThumbnailBrush_PData); 66 | 67 | */ 68 | FSlateStyleRegistry::RegisterSlateStyle(*StyleSet.Get()); 69 | 70 | } 71 | 72 | 73 | 74 | 75 | // Register asset types 76 | IAssetTools& AssetTools = FModuleManager::LoadModuleChecked("AssetTools").Get(); 77 | FaceAndroidAssetCategory = AssetTools.RegisterAdvancedAssetCategory(FName(TEXT("FaceAndroid")), LOCTEXT("FaceAndroidAssetCategory", "FaceAndroid")); 78 | 79 | // Register asset type actions for DatasmithScene class 80 | //TSharedPtr EcoSystemAssetTypeAction = MakeShared(); 81 | //AssetTools.RegisterAssetTypeActions(EcoSystemAssetTypeAction.ToSharedRef()); 82 | 83 | // Helper lambda for registering asset type actions for automatic cleanup on shutdown 84 | auto RegisterAssetTypeAction = [&](TSharedRef Action) 85 | { 86 | AssetTools.RegisterAssetTypeActions(Action); 87 | CreatedAssetTypeActions.Add(Action); 88 | }; 89 | 90 | // Register type actions 91 | RegisterAssetTypeAction(MakeShareable(new FAndroidBlenshapeAssetTypeActions)); 92 | RegisterAssetTypeAction(MakeShareable(new FAndroidBlenshapeWeightsAssetTypeActions)); 93 | /* 94 | 95 | 96 | RegisterAssetTypeAction(MakeShareable(new FPlanetGroundMaterialAssetTypeActions)); 97 | RegisterAssetTypeAction(MakeShareable(new FPlanetStaticEcoDataAssetTypeActions)); 98 | */ 99 | } 100 | 101 | void FAndroidFaceCaptureEditor::ShutdownModule() 102 | { 103 | FSlateStyleRegistry::UnRegisterSlateStyle(StyleSet->GetStyleSetName()); 104 | 105 | if (FModuleManager::Get().IsModuleLoaded("AssetTools")) 106 | { 107 | IAssetTools& AssetTools = FModuleManager::GetModuleChecked("AssetTools").Get(); 108 | for (auto CreatedAssetTypeAction : CreatedAssetTypeActions) 109 | { 110 | AssetTools.UnregisterAssetTypeActions(CreatedAssetTypeAction.ToSharedRef()); 111 | } 112 | } 113 | CreatedAssetTypeActions.Empty(); 114 | } 115 | 116 | #undef LOCTEXT_NAMESPACE 117 | 118 | 119 | -------------------------------------------------------------------------------- /Source/AndroidFaceCaptureEditor/AndroidFaceCaptureEditor.h: -------------------------------------------------------------------------------- 1 | // Copyright Epic Games, Inc. All Rights Reserved. 2 | 3 | #pragma once 4 | 5 | #include "CoreMinimal.h" 6 | #include "Modules/ModuleManager.h" 7 | 8 | #include "Styling/SlateStyle.h" 9 | #include "Styling/SlateStyleRegistry.h" 10 | #include "AssetToolsModule.h" 11 | #include "AssetTypeCategories.h" 12 | 13 | class FAndroidFaceCaptureEditor : public FDefaultGameModuleImpl 14 | { 15 | public: 16 | virtual void StartupModule() override; 17 | virtual void ShutdownModule() override; 18 | static EAssetTypeCategories::Type GetAssetCategory() { return FaceAndroidAssetCategory; } 19 | 20 | public: 21 | 22 | TSharedPtr StyleSet; 23 | 24 | static EAssetTypeCategories::Type FaceAndroidAssetCategory; 25 | TArray> CreatedAssetTypeActions; 26 | }; 27 | 28 | --------------------------------------------------------------------------------