/** * @file * * @author Mamadou Babaei * * @section LICENSE * * (The MIT License) * * Copyright (c) 2020 - 2022 SenseGlove * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * * @section DESCRIPTION * * */ #include "SGCore/SGHandPose.h" #include "Runtime/Launch/Resources/Version.h" #include "SGCore/SGRotatorArray.h" #include "SGCoreImpl/SGExportedFunctions.h" #include "SGCoreImpl/SGHandPoseImpl.h" #include "SGInterop/SGIC_ESGFinger.h" #include "SGInterop/SGIC_FSGBasicHandModelImpl.h" #include "SGInterop/SGIC_FSGHandPoseImpl.h" #include "SGInterop/SGIC_FString.h" #include "SGInterop/SGIC_TArray_float.h" #include "SGInterop/SGIC_TArray_TArray_FQuat.h" #include "SGInterop/SGIC_TArray_TArray_FVector.h" struct USGHandPose::FImpl { /************************ * Member variables ************************/ FSGHandPoseImpl HandPoseImpl; /************************ * Owner object ************************/ USGHandPose* Owner; /************************ * Constructor / Destructor ************************/ explicit FImpl(USGHandPose* InOwner); ~FImpl(); /************************ * Default copy constructor & copy assignment operator ************************/ FImpl(const FImpl& Rhs) = default; FImpl& operator=(const FImpl& Rhs) = default; /************************ * Methods ************************/ void SyncUProperties(); void SyncImplObject(); }; USGHandPose* USGHandPose::NewHandPose(UObject* Outer, const FSGHandPoseImpl& HandPoseImpl) { USGHandPose* Instance = NewObject(Outer); Instance->SetHandPoseImpl(HandPoseImpl); return Instance; } USGHandPose* USGHandPose::NewHandPose(UObject* Outer) { FSGIC_FSGHandPoseImpl OutHandPoseImplContainer; SGCoreImpl_FSGHandPoseImpl_ctor(&OutHandPoseImplContainer); return NewHandPose(Outer, MoveTemp(OutHandPoseImplContainer.HandPoseImpl)); } USGHandPose* USGHandPose::NewHandPose( UObject* Outer, const bool bRightHanded, const TArray>& JointPositions, const TArray>& JointRotations, const TArray>& HandAngles) { FSGIC_FSGHandPoseImpl OutHandPoseImplContainer; FSGIC_TArray_TArray_FVector JointPositionsContainer{JointPositions}; FSGIC_TArray_TArray_FQuat JointRotationsContainer{JointRotations}; FSGIC_TArray_TArray_FVector HandAnglesContainer{HandAngles}; SGCoreImpl_FSGHandPoseImpl_ctor_bRightHanded_JointPositions_JointRotations_HandAngles( &OutHandPoseImplContainer, bRightHanded, &JointPositionsContainer, &JointRotationsContainer, &HandAnglesContainer); return NewHandPose(Outer, MoveTemp(OutHandPoseImplContainer.HandPoseImpl)); } USGHandPose* USGHandPose::NewHandPose( UObject* Outer, const bool bRightHanded, const TArray>& JointPositions, const TArray>& JointRotations, const TArray>& HandAngles) { FSGIC_FSGHandPoseImpl OutHandPoseImplContainer; FSGIC_TArray_TArray_FVector JointPositionsContainer{JointPositions}; FSGIC_TArray_TArray_FQuat JointRotationsContainer{FSGArrayUtils::RotatorsToQuats(JointRotations)}; FSGIC_TArray_TArray_FVector HandAnglesContainer{HandAngles}; SGCoreImpl_FSGHandPoseImpl_ctor_bRightHanded_JointPositions_JointRotations_HandAngles( &OutHandPoseImplContainer, bRightHanded, &JointPositionsContainer, &JointRotationsContainer, &HandAnglesContainer); return NewHandPose(Outer, MoveTemp(OutHandPoseImplContainer.HandPoseImpl)); } USGHandPose* USGHandPose::NewHandPose( UObject* Outer, const bool bRightHanded, const TArray& JointPositions, const TArray& JointRotations, const TArray& HandAngles) { FSGIC_FSGHandPoseImpl OutHandPoseImplContainer; FSGIC_TArray_TArray_FVector JointPositionsContainer{ FSGArrayUtils::FromNestedBPArray(JointPositions) }; FSGIC_TArray_TArray_FQuat JointRotationsContainer{ FSGArrayUtils::FromNestedBPArray(JointRotations) }; FSGIC_TArray_TArray_FVector HandAnglesContainer{ FSGArrayUtils::FromNestedBPArray(HandAngles) }; SGCoreImpl_FSGHandPoseImpl_ctor_bRightHanded_JointPositions_JointRotations_HandAngles( &OutHandPoseImplContainer, bRightHanded, &JointPositionsContainer, &JointRotationsContainer, &HandAnglesContainer); return NewHandPose(Outer, MoveTemp(OutHandPoseImplContainer.HandPoseImpl)); } USGHandPose* USGHandPose::NewHandPose( UObject* Outer, const bool bRightHanded, const TArray& JointPositions, const TArray& JointRotations, const TArray& HandAngles) { FSGIC_FSGHandPoseImpl OutHandPoseImplContainer; FSGIC_TArray_TArray_FVector JointPositionsContainer{ FSGArrayUtils::FromNestedBPArray(JointPositions) }; FSGIC_TArray_TArray_FQuat JointRotationsContainer{ FSGArrayUtils::RotatorsToQuats(JointRotations) }; FSGIC_TArray_TArray_FVector HandAnglesContainer{ FSGArrayUtils::FromNestedBPArray(HandAngles) }; SGCoreImpl_FSGHandPoseImpl_ctor_bRightHanded_JointPositions_JointRotations_HandAngles( &OutHandPoseImplContainer, bRightHanded, &JointPositionsContainer, &JointRotationsContainer, &HandAnglesContainer); return NewHandPose(Outer, MoveTemp(OutHandPoseImplContainer.HandPoseImpl)); } USGHandPose* USGHandPose::Deserialize(UObject* Outer, const FString& SerializedString) { FSGIC_FSGHandPoseImpl OutHandPoseImplContainer; FSGIC_FString SerializedStringContainer{SerializedString}; SGCoreImpl_FSGHandPoseImpl_Deserialize(&OutHandPoseImplContainer, &SerializedStringContainer); return NewHandPose(Outer, MoveTemp(OutHandPoseImplContainer.HandPoseImpl)); } USGHandPose* USGHandPose::FromHandAngles(UObject* Outer, const TArray>& HandAngles, const bool bRightHanded, const USGBasicHandModel* HandDimensions) { FSGIC_FSGHandPoseImpl OutHandPoseImplContainer; FSGIC_TArray_TArray_FVector HandAnglesContainer{HandAngles}; FSGIC_FSGBasicHandModelImpl HandDimensionsContainer{HandDimensions->ToBasicHandModelImpl()}; SGCoreImpl_FSGHandPoseImpl_FromHandAngles_HandAngles_bRightHanded_HandDimensions( &OutHandPoseImplContainer, &HandAnglesContainer, bRightHanded, &HandAnglesContainer); return NewHandPose(Outer, MoveTemp(OutHandPoseImplContainer.HandPoseImpl)); } USGHandPose* USGHandPose::FromHandAngles(UObject* Outer, const TArray>& HandAngles, const bool bRightHanded) { FSGIC_FSGHandPoseImpl OutHandPoseImplContainer; FSGIC_TArray_TArray_FVector HandAnglesContainer{HandAngles}; SGCoreImpl_FSGHandPoseImpl_FromHandAngles_HandAngles_bRightHanded( &OutHandPoseImplContainer, &HandAnglesContainer, bRightHanded); return NewHandPose(Outer, MoveTemp(OutHandPoseImplContainer.HandPoseImpl)); } USGHandPose* USGHandPose::DefaultIdle(UObject* Outer, const bool bRightHanded, const USGBasicHandModel* HandDimensions) { FSGIC_FSGHandPoseImpl OutHandPoseImplContainer; FSGIC_FSGBasicHandModelImpl HandDimensionsContainer{HandDimensions->ToBasicHandModelImpl()}; SGCoreImpl_FSGHandPoseImpl_DefaultIdle_bRightHanded_HandDimensions( &OutHandPoseImplContainer, bRightHanded, &HandDimensionsContainer); return NewHandPose(Outer, MoveTemp(OutHandPoseImplContainer.HandPoseImpl)); } USGHandPose* USGHandPose::DefaultIdle(UObject* Outer, const bool bRightHanded) { FSGIC_FSGHandPoseImpl OutHandPoseImplContainer; SGCoreImpl_FSGHandPoseImpl_DefaultIdle_bRightHanded(&OutHandPoseImplContainer, bRightHanded); return NewHandPose(Outer, MoveTemp(OutHandPoseImplContainer.HandPoseImpl)); } USGHandPose* USGHandPose::FlatHand(UObject* Outer, const bool bRightHanded, const USGBasicHandModel* HandDimensions) { FSGIC_FSGHandPoseImpl OutHandPoseImplContainer; FSGIC_FSGBasicHandModelImpl HandDimensionsContainer{HandDimensions->ToBasicHandModelImpl()}; SGCoreImpl_FSGHandPoseImpl_FlatHand_bRightHanded_HandDimensions( &OutHandPoseImplContainer, bRightHanded, &HandDimensionsContainer); return NewHandPose(Outer, MoveTemp(OutHandPoseImplContainer.HandPoseImpl)); } USGHandPose* USGHandPose::FlatHand(UObject* Outer, const bool bRightHanded) { FSGIC_FSGHandPoseImpl OutHandPoseImplContainer; SGCoreImpl_FSGHandPoseImpl_FlatHand_bRightHanded(&OutHandPoseImplContainer, bRightHanded); return NewHandPose(Outer, MoveTemp(OutHandPoseImplContainer.HandPoseImpl)); } USGHandPose* USGHandPose::ThumbsUp(UObject* Outer, const bool bRightHanded, const USGBasicHandModel* HandDimensions) { FSGIC_FSGHandPoseImpl OutHandPoseImplContainer; FSGIC_FSGBasicHandModelImpl HandDimensionsContainer{HandDimensions->ToBasicHandModelImpl()}; SGCoreImpl_FSGHandPoseImpl_ThumbsUp_bRightHanded_HandDimensions( &OutHandPoseImplContainer, bRightHanded, &HandDimensionsContainer); return NewHandPose(Outer, MoveTemp(OutHandPoseImplContainer.HandPoseImpl)); } USGHandPose* USGHandPose::ThumbsUp(UObject* Outer, const bool bRightHanded) { FSGIC_FSGHandPoseImpl OutHandPoseImplContainer; SGCoreImpl_FSGHandPoseImpl_ThumbsUp_bRightHanded(&OutHandPoseImplContainer, bRightHanded); return NewHandPose(Outer, MoveTemp(OutHandPoseImplContainer.HandPoseImpl)); } USGHandPose* USGHandPose::Fist(UObject* Outer, const bool bRightHanded, const USGBasicHandModel* HandDimensions) { FSGIC_FSGHandPoseImpl OutHandPoseImplContainer; FSGIC_FSGBasicHandModelImpl HandDimensionsContainer{HandDimensions->ToBasicHandModelImpl()}; SGCoreImpl_FSGHandPoseImpl_Fist_bRightHanded_HandDimensions( &OutHandPoseImplContainer, bRightHanded, &HandDimensionsContainer); return NewHandPose(Outer, MoveTemp(OutHandPoseImplContainer.HandPoseImpl)); } USGHandPose* USGHandPose::Fist(UObject* Outer, const bool bRightHanded) { FSGIC_FSGHandPoseImpl OutHandPoseImplContainer; SGCoreImpl_FSGHandPoseImpl_Fist_bRightHanded(&OutHandPoseImplContainer, bRightHanded); return NewHandPose(Outer, MoveTemp(OutHandPoseImplContainer.HandPoseImpl)); } USGHandPose::USGHandPose() : #if ENGINE_MAJOR_VERSION == 5 || ( ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION > 22 ) Pimpl(TUniquePtr(new FImpl{this}, PimplDeleter)) #else Pimpl(TUniquePtr(new FImpl{this})) #endif /* ENGINE_MAJOR_VERSION == 5 || ( ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION > 22 ) */ { FSGIC_FSGHandPoseImpl OutHandPoseImplContainer; SGCoreImpl_FSGHandPoseImpl_ctor(&OutHandPoseImplContainer); Pimpl->HandPoseImpl = MoveTemp(OutHandPoseImplContainer.HandPoseImpl); Pimpl->SyncUProperties(); } USGHandPose::USGHandPose(const bool bRightHanded, const TArray>& JointPositions, const TArray>& JointRotations, const TArray>& HandAngles) : #if ENGINE_MAJOR_VERSION == 5 || ( ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION > 22 ) Pimpl(TUniquePtr(new FImpl{this}, PimplDeleter)) #else Pimpl(TUniquePtr(new FImpl{this})) #endif /* ENGINE_MAJOR_VERSION == 5 || ( ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION > 22 ) */ { FSGIC_FSGHandPoseImpl OutHandPoseImplContainer; FSGIC_TArray_TArray_FVector JointPositionsContainer{JointPositions}; FSGIC_TArray_TArray_FQuat JointRotationsContainer{JointRotations}; FSGIC_TArray_TArray_FVector HandAnglesContainer{HandAngles}; SGCoreImpl_FSGHandPoseImpl_ctor_bRightHanded_JointPositions_JointRotations_HandAngles( &OutHandPoseImplContainer, bRightHanded, &JointPositionsContainer, &JointRotationsContainer, &HandAnglesContainer); Pimpl->HandPoseImpl = MoveTemp(OutHandPoseImplContainer.HandPoseImpl); Pimpl->SyncUProperties(); } USGHandPose::USGHandPose(const bool bRightHanded, const TArray>& JointPositions, const TArray>& JointRotations, const TArray>& HandAngles) : #if ENGINE_MAJOR_VERSION == 5 || ( ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION > 22 ) Pimpl(TUniquePtr(new FImpl{this}, PimplDeleter)) #else Pimpl(TUniquePtr(new FImpl{this})) #endif /* ENGINE_MAJOR_VERSION == 5 || ( ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION > 22 ) */ { FSGIC_FSGHandPoseImpl OutHandPoseImplContainer; FSGIC_TArray_TArray_FVector JointPositionsContainer{JointPositions}; FSGIC_TArray_TArray_FQuat JointRotationsContainer{FSGArrayUtils::RotatorsToQuats(JointRotations)}; FSGIC_TArray_TArray_FVector HandAnglesContainer{HandAngles}; SGCoreImpl_FSGHandPoseImpl_ctor_bRightHanded_JointPositions_JointRotations_HandAngles( &OutHandPoseImplContainer, bRightHanded, &JointPositionsContainer, &JointRotationsContainer, &HandAnglesContainer); Pimpl->HandPoseImpl = MoveTemp(OutHandPoseImplContainer.HandPoseImpl); Pimpl->SyncUProperties(); } USGHandPose::USGHandPose(const bool bRightHanded, const TArray& JointPositions, const TArray& JointRotations, const TArray& HandAngles) : #if ENGINE_MAJOR_VERSION == 5 || ( ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION > 22 ) Pimpl(TUniquePtr(new FImpl{this}, PimplDeleter)) #else Pimpl(TUniquePtr(new FImpl{this})) #endif /* ENGINE_MAJOR_VERSION == 5 || ( ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION > 22 ) */ { FSGIC_FSGHandPoseImpl OutHandPoseImplContainer; FSGIC_TArray_TArray_FVector JointPositionsContainer{ FSGArrayUtils::FromNestedBPArray(JointPositions) }; FSGIC_TArray_TArray_FQuat JointRotationsContainer{ FSGArrayUtils::FromNestedBPArray(JointRotations) }; FSGIC_TArray_TArray_FVector HandAnglesContainer{ FSGArrayUtils::FromNestedBPArray(HandAngles) }; SGCoreImpl_FSGHandPoseImpl_ctor_bRightHanded_JointPositions_JointRotations_HandAngles( &OutHandPoseImplContainer, bRightHanded, &JointPositionsContainer, &JointRotationsContainer, &HandAnglesContainer); Pimpl->HandPoseImpl = MoveTemp(OutHandPoseImplContainer.HandPoseImpl); Pimpl->SyncUProperties(); } USGHandPose::USGHandPose(const bool bRightHanded, const TArray& JointPositions, const TArray& JointRotations, const TArray& HandAngles) : #if ENGINE_MAJOR_VERSION == 5 || ( ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION > 22 ) Pimpl(TUniquePtr(new FImpl{this}, PimplDeleter)) #else Pimpl(TUniquePtr(new FImpl{this})) #endif /* ENGINE_MAJOR_VERSION == 5 || ( ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION > 22 ) */ { FSGIC_FSGHandPoseImpl OutHandPoseImplContainer; FSGIC_TArray_TArray_FVector JointPositionsContainer{ FSGArrayUtils::FromNestedBPArray(JointPositions) }; FSGIC_TArray_TArray_FQuat JointRotationsContainer{ FSGArrayUtils::RotatorsToQuats(JointRotations) }; FSGIC_TArray_TArray_FVector HandAnglesContainer{ FSGArrayUtils::FromNestedBPArray(HandAngles) }; SGCoreImpl_FSGHandPoseImpl_ctor_bRightHanded_JointPositions_JointRotations_HandAngles( &OutHandPoseImplContainer, bRightHanded, &JointPositionsContainer, &JointRotationsContainer, &HandAnglesContainer); Pimpl->HandPoseImpl = MoveTemp(OutHandPoseImplContainer.HandPoseImpl); Pimpl->SyncUProperties(); } USGHandPose::USGHandPose(const FSGHandPoseImpl& HandPoseImpl) : #if ENGINE_MAJOR_VERSION == 5 || ( ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION > 22 ) Pimpl(TUniquePtr(new FImpl{this}, PimplDeleter)) #else Pimpl(TUniquePtr(new FImpl{this})) #endif /* ENGINE_MAJOR_VERSION == 5 || ( ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION > 22 ) */ { SetHandPoseImpl(HandPoseImpl); Pimpl->SyncUProperties(); } USGHandPose::~USGHandPose() = default; void USGHandPose::SetHandPoseImpl(const FSGHandPoseImpl& HandPoseImpl) { FSGIC_FSGHandPoseImpl OutHandPoseContainer; FSGIC_FSGHandPoseImpl RhsContainer{HandPoseImpl}; SGCoreImpl_FSGHandPoseImpl_ctor_copy(&OutHandPoseContainer, &RhsContainer); Pimpl->HandPoseImpl = MoveTemp(OutHandPoseContainer.HandPoseImpl); } const FSGHandPoseImpl& USGHandPose::ToHandPoseImpl() const { Pimpl->SyncImplObject(); return Pimpl->HandPoseImpl; } bool USGHandPose::IsRight() const { FSGIC_FSGHandPoseImpl InstanceContainer{ToHandPoseImpl()}; return SGCoreImpl_FSGHandPoseImpl_IsRight(&InstanceContainer); } TArray> USGHandPose::GetJointPositions() const { FSGIC_FSGHandPoseImpl InstanceContainer{ToHandPoseImpl()}; FSGIC_TArray_TArray_FVector OutPositionsContainer; SGCoreImpl_FSGHandPoseImpl_GetJointPositions(&InstanceContainer, &OutPositionsContainer); return MoveTemp(OutPositionsContainer.Array); } TArray> USGHandPose::GetJointRotationsQ() const { FSGIC_FSGHandPoseImpl InstanceContainer{ToHandPoseImpl()}; FSGIC_TArray_TArray_FQuat OutRotationsContainer; SGCoreImpl_FSGHandPoseImpl_GetJointRotations(&InstanceContainer, &OutRotationsContainer); return MoveTemp(OutRotationsContainer.Array); } TArray> USGHandPose::GetJointRotations() const { FSGIC_FSGHandPoseImpl InstanceContainer{ToHandPoseImpl()}; FSGIC_TArray_TArray_FQuat OutRotationsContainer; SGCoreImpl_FSGHandPoseImpl_GetJointRotations(&InstanceContainer, &OutRotationsContainer); return FSGArrayUtils::QuatsToRotators(OutRotationsContainer.Array); } TArray> USGHandPose::GetHandAngles() const { FSGIC_FSGHandPoseImpl InstanceContainer{ToHandPoseImpl()}; FSGIC_TArray_TArray_FVector OutAnglesContainer; SGCoreImpl_FSGHandPoseImpl_GetHandAngles(&InstanceContainer, &OutAnglesContainer); return MoveTemp(OutAnglesContainer.Array); } bool USGHandPose::Equals(const USGHandPose* HandPose) const { Pimpl->SyncImplObject(); FSGIC_FSGHandPoseImpl InstanceContainer{ToHandPoseImpl()}; FSGIC_FSGHandPoseImpl HandPoseContainer{HandPose->ToHandPoseImpl()}; return SGCoreImpl_FSGHandPoseImpl_Equals(&InstanceContainer, &HandPoseContainer); } float USGHandPose::GetNormalizedFlexion(const ESGFinger Finger, const bool bClamp01) const { Pimpl->SyncImplObject(); FSGIC_FSGHandPoseImpl InstanceContainer{ToHandPoseImpl()}; FSGIC_ESGFinger FingerContainer{Finger}; return SGCoreImpl_FSGHandPoseImpl_GetNormalizedFlexion_Finger_bClamp01( &InstanceContainer, &FingerContainer, bClamp01); } TArray USGHandPose::GetNormalizedFlexion(const bool bClamp01) const { Pimpl->SyncImplObject(); FSGIC_FSGHandPoseImpl InstanceContainer{ToHandPoseImpl()}; FSGIC_TArray_float OutFlexionContainer; SGCoreImpl_FSGHandPoseImpl_GetNormalizedFlexion_bClamp01(&InstanceContainer, &OutFlexionContainer, bClamp01); return MoveTemp(OutFlexionContainer.Array); } FString USGHandPose::ToString(const bool bShortFormat) const { Pimpl->SyncImplObject(); FSGIC_FSGHandPoseImpl InstanceContainer{ToHandPoseImpl()}; FSGIC_FString OutStringContainer; SGCoreImpl_FSGHandPoseImpl_ToString(&InstanceContainer, &OutStringContainer, bShortFormat); return MoveTemp(OutStringContainer.String); } FString USGHandPose::SGSerialize() const { Pimpl->SyncImplObject(); FSGIC_FSGHandPoseImpl InstanceContainer{ToHandPoseImpl()}; FSGIC_FString OutStringContainer; SGCoreImpl_FSGHandPoseImpl_Serialize(&InstanceContainer, &OutStringContainer); return MoveTemp(OutStringContainer.String); } USGHandPose::FImpl::FImpl(USGHandPose* InOwner) : Owner(InOwner) { } USGHandPose::FImpl::~FImpl() = default; void USGHandPose::FImplDeleter::operator()(const FImpl* P) const { delete P; } void USGHandPose::FImpl::SyncUProperties() { } void USGHandPose::FImpl::SyncImplObject() { }