add a new component-based class for the virtual hand

This commit is contained in:
Mamadou Babaei
2023-03-28 10:39:08 +02:00
parent 4e9df4b1b9
commit f5750217da
4 changed files with 857 additions and 0 deletions
@@ -0,0 +1,470 @@
/**
* @file
*
* @author Mamadou Babaei <mamadou@senseglove.com>
*
* @section LICENSE
*
* (The MIT License)
*
* Copyright (c) 2020 - 2023 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 "SenseGlove/Components/SGVirtualHandMeshComponent.h"
#include "Animation/Skeleton.h"
#include "Components/SkeletalMeshComponent.h"
#include "Engine/SkeletalMesh.h"
#include "UObject/ConstructorHelpers.h"
#include "SenseGlove/Animation/SGVirtualHandAnimInstance.h"
#include "SGCore/SGHandPose.h"
#include "SGCore/SGHapticGlove.h"
#include "SGLog/SGLog.h"
struct USGVirtualHandMeshComponent::FImpl
{
/************************
* Static methods
************************/
FORCEINLINE static const FString& GetDefaultLeftHandMeshPath()
{
static const FString Path{TEXT("SkeletalMesh'/SenseGlove/Meshes/"
"SK_SenseGlove_VirtualHand_Left.SK_SenseGlove_VirtualHand_Left'")};
return Path;
}
FORCEINLINE static const FString& GetDefaultLeftHandMeshPathOnly()
{
static const FString Path{TEXT("/SenseGlove/Meshes/"
"SK_SenseGlove_VirtualHand_Left.SK_SenseGlove_VirtualHand_Left")};
return Path;
}
FORCEINLINE static const FString& GetDefaultRightHandMeshPath()
{
static const FString Path{TEXT("SkeletalMesh'/SenseGlove/Meshes/"
"SK_SenseGlove_VirtualHand_Right.SK_SenseGlove_VirtualHand_Right'")};
return Path;
}
FORCEINLINE static const FString& GetDefaultRightHandMeshPathOnly()
{
static const FString Path{TEXT("/SenseGlove/Meshes/"
"SK_SenseGlove_VirtualHand_Right.SK_SenseGlove_VirtualHand_Right")};
return Path;
}
/************************
* Owner object
************************/
USGVirtualHandMeshComponent* Owner;
/************************
* Constructor / Destructor
************************/
explicit FImpl(USGVirtualHandMeshComponent* InOwner);
~FImpl();
/************************
* Default copy constructor & copy assignment operator
************************/
FImpl(const FImpl& Rhs) = default;
FImpl& operator=(const FImpl& Rhs) = default;
/************************
* Methods
************************/
bool IsEditor() const;
FString GetDefaultMeshPath() const;
bool IsUsingUserMesh() const;
USkeletalMesh* LoadDefaultMesh() const;
void SetDefaultMesh() const;
USkeletalMesh* GetMesh() const;
USkeleton* GetSkeleton() const;
const FReferenceSkeleton& GetRefSkeleton() const;
bool CheckGlove() const;
};
const TArray<TArray<FName>>& USGVirtualHandMeshComponent::GetLeftHandFingerBoneNames()
{
static const TArray<TArray<FName>> BoneNames{
{FName(TEXT("thumb_01_l")), FName(TEXT("thumb_02_l")), FName(TEXT("thumb_03_l"))},
{FName(TEXT("index_01_l")), FName(TEXT("index_02_l")), FName(TEXT("index_03_l"))},
{FName(TEXT("middle_01_l")), FName(TEXT("middle_02_l")), FName(TEXT("middle_03_l"))},
{FName(TEXT("ring_01_l")), FName(TEXT("ring_02_l")), FName(TEXT("ring_03_l"))},
{FName(TEXT("pinky_01_l")), FName(TEXT("pinky_02_l")), FName(TEXT("pinky_03_l"))},
};
return BoneNames;
}
const TArray<TArray<FName>>& USGVirtualHandMeshComponent::GetRightHandFingerBoneNames()
{
static const TArray<TArray<FName>> BoneNames{
{FName(TEXT("thumb_01_r")), FName(TEXT("thumb_02_r")), FName(TEXT("thumb_03_r"))},
{FName(TEXT("index_01_r")), FName(TEXT("index_02_r")), FName(TEXT("index_03_r"))},
{FName(TEXT("middle_01_r")), FName(TEXT("middle_02_r")), FName(TEXT("middle_03_r"))},
{FName(TEXT("ring_01_r")), FName(TEXT("ring_02_r")), FName(TEXT("ring_03_r"))},
{FName(TEXT("pinky_01_r")), FName(TEXT("pinky_02_r")), FName(TEXT("pinky_03_r"))},
};
return BoneNames;
}
const FName& USGVirtualHandMeshComponent::GetLeftHandFingerBoneName(const int32 Finger, const int32 Joint)
{
const TArray<TArray<FName>>& BoneNames{GetLeftHandFingerBoneNames()};
ensureAlwaysMsgf(Finger < BoneNames.Num(), TEXT("Finger index is out of bound!"));
ensureAlwaysMsgf(Joint < BoneNames[Finger].Num(), TEXT("Joint index is out of bound!"));
const FName& BoneName{BoneNames[Finger][Joint]};
return BoneName;
}
const FName& USGVirtualHandMeshComponent::GetRightHandFingerBoneName(const int32 Finger, const int32 Joint)
{
const TArray<TArray<FName>>& BoneNames{GetRightHandFingerBoneNames()};
ensureAlwaysMsgf(Finger < BoneNames.Num(), TEXT("Finger index is out of bound!"));
ensureAlwaysMsgf(Joint < BoneNames[Finger].Num(), TEXT("Joint index is out of bound!"));
const FName& BoneName{BoneNames[Finger][Joint]};
return BoneName;
}
USGVirtualHandMeshComponent::USGVirtualHandMeshComponent(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer),
Pimpl(TUniquePtr<FImpl, FImplDeleter>(new FImpl{this}, PimplDeleter))
{
PrimaryComponentTick.bTickEvenWhenPaused = false;
PrimaryComponentTick.bCanEverTick = true;
PrimaryComponentTick.bStartWithTickEnabled = true;
bTickInEditor = true;
bNeverNeedsRenderUpdate = false;
bAllowConcurrentTick = true;
SetCastShadow(true);
SetCastHiddenShadow(false);
bCastDynamicShadow = true;
SetOnlyOwnerSee(false);
SetReceivesDecals(true);
SetCanEverAffectNavigation(false);
Super::SetCollisionObjectType(ECC_WorldDynamic);
Super::SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);
Super::SetCollisionResponseToAllChannels(ECR_Overlap);
Super::SetCollisionResponseToChannel(ECC_WorldStatic, ECR_Block);
Super::SetCollisionResponseToChannel(ECC_WorldDynamic, ECR_Block);
Super::SetCollisionResponseToChannel(ECC_Pawn, ECR_Block);
Super::SetCollisionResponseToChannel(ECC_Visibility, ECR_Block);
Super::SetCollisionResponseToChannel(ECC_PhysicsBody, ECR_Block);
Super::SetCollisionResponseToChannel(ECC_Vehicle, ECR_Block);
Super::SetCollisionResponseToChannel(ECC_Destructible, ECR_Block);
Super::SetAnimClass(USGVirtualHandAnimInstance::StaticClass());
bRight = true;
bHiddenInGameIfNoGloveDetected = true;
const FString SkeletalMeshPath(Pimpl->GetDefaultMeshPath());
const ConstructorHelpers::FObjectFinder<USkeletalMesh> SkeletalMesh(*SkeletalMeshPath);
ensureAlwaysMsgf(SkeletalMesh.Succeeded() && SkeletalMesh.Object,
TEXT("Failed to load the skeletal mesh: '%s'"), *SkeletalMeshPath);
Super::SetSkeletalMesh(SkeletalMesh.Object, true);
Glove = nullptr;
}
void USGVirtualHandMeshComponent::SetAnimClass(UClass* NewClass)
{
ensureAlwaysMsgf(Cast<USGVirtualHandAnimInstance>(NewClass),
TEXT("The AnimInstance class must be a subclass of USGVirtualHandAnimInstance!"));
Super::SetAnimClass(NewClass);
}
void USGVirtualHandMeshComponent::InitializeComponent()
{
Super::InitializeComponent();
if (!Pimpl->IsUsingUserMesh())
{
Pimpl->SetDefaultMesh();
}
}
void USGVirtualHandMeshComponent::TickComponent(
const float DeltaTime, const ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
#if WITH_EDITOR
if (Pimpl->IsEditor())
{
EditorTick(DeltaTime, TickType, ThisTickFunction);
return;
}
#endif
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
(void) Pimpl->CheckGlove();
}
void USGVirtualHandMeshComponent::SetSkeletalMesh(USkeletalMesh* NewMesh, const bool bReinitPose)
{
if (IsValid(NewMesh))
{
Super::SetSkeletalMesh(NewMesh, bReinitPose);
}
else
{
Super::SetSkeletalMesh(Pimpl->LoadDefaultMesh(), bReinitPose);
}
}
void USGVirtualHandMeshComponent::EditorTick(
const float DeltaTime, const ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
(void) Pimpl->CheckGlove();
}
bool USGVirtualHandMeshComponent::IsGloveConnected() const
{
return Pimpl->CheckGlove();
}
USGHandPose* USGVirtualHandMeshComponent::GetHandPose()
{
USGHandPose* HandPose = nullptr;
if (IsValid(Glove))
{
Glove->GetHandPose(this, HandPose);
}
return HandPose;
}
const FName& USGVirtualHandMeshComponent::GetFingerBoneName(const int32 Finger, const int32 Joint) const
{
const FName& Name{IsRight()
? GetRightHandFingerBoneName(Finger, Joint)
: GetLeftHandFingerBoneName(Finger, Joint)};
return Name;
}
const FTransform& USGVirtualHandMeshComponent::GetFingerBoneRefTransform(const int32 Finger, const int32 Joint) const
{
const FName& BoneName{GetFingerBoneName(Finger, Joint)};
const FReferenceSkeleton& ReferenceSkeleton{Pimpl->GetRefSkeleton()};
const int32 BoneIndex = ReferenceSkeleton.FindBoneIndex(BoneName);
ensureAlwaysMsgf(BoneIndex != INDEX_NONE, TEXT("Invalid virtual hand bone name '%s' or index!"),
*BoneName.ToString());
const FTransform& BoneTransform{ReferenceSkeleton.GetRefBonePose()[BoneIndex]};
return BoneTransform;
}
FRotator USGVirtualHandMeshComponent::GetFingerBoneRefRotation(const int32 Finger, const int32 Joint) const
{
const FTransform BoneTransform{GetFingerBoneRefTransform(Finger, Joint)};
FRotator BoneRotation{BoneTransform.GetRotation().Rotator()};
return MoveTemp(BoneRotation);
}
TMap<FName, FRotator> USGVirtualHandMeshComponent::GetFingersBonesRotations()
{
TMap<FName, FRotator> Rotations;
const USGHandPose* HandPose = GetHandPose();
if (!IsValid(HandPose))
{
return MoveTemp(Rotations);
}
const TArray<TArray<FVector>> HandAngles{HandPose->GetHandAngles()};
for (int32 FingerIndex = 0; FingerIndex < HandAngles.Num(); ++FingerIndex)
{
const TArray<FVector>& FingerJointAngles{HandAngles[FingerIndex]};
for (int32 JointIndex = 0; JointIndex < FingerJointAngles.Num(); ++JointIndex)
{
const FVector& JointAngle{FingerJointAngles[JointIndex]};
const FQuat JointRotation{FQuat::MakeFromEuler(JointAngle)};
const FTransform& BoneRefTransform{GetFingerBoneRefTransform(FingerIndex, JointIndex)};
FQuat NewBoneRotation{BoneRefTransform.GetRotation() * JointRotation};
FName BoneName{GetFingerBoneName(FingerIndex, JointIndex)};
Rotations.Emplace(MoveTemp(BoneName), MoveTemp(NewBoneRotation));
}
}
return MoveTemp(Rotations);
}
USGVirtualHandMeshComponent::FImpl::FImpl(USGVirtualHandMeshComponent* InOwner)
: Owner(InOwner)
{
}
USGVirtualHandMeshComponent::FImpl::~FImpl() = default;
bool USGVirtualHandMeshComponent::FImpl::IsEditor() const
{
const UWorld* World = Owner->GetWorld();
if (World && World->WorldType == EWorldType::Editor)
{
return true;
}
return false;
}
FString USGVirtualHandMeshComponent::FImpl::GetDefaultMeshPath() const
{
FString SkeletalMeshPath;
if (Owner->bRight)
{
SkeletalMeshPath = GetDefaultRightHandMeshPath();
}
else
{
SkeletalMeshPath = GetDefaultLeftHandMeshPath();
}
return MoveTemp(SkeletalMeshPath);
}
bool USGVirtualHandMeshComponent::FImpl::IsUsingUserMesh() const
{
const USkeletalMesh* SkeletalMesh{GetMesh()};
if (!IsValid(SkeletalMesh))
{
return false;
}
const FString CurrentMeshPath(SkeletalMesh->GetPathName());
const FString LeftHandDefaultMeshPath(GetDefaultLeftHandMeshPath());
const FString LeftHandDefaultMeshPathOnly(GetDefaultLeftHandMeshPathOnly());
const FString RightHandDefaultMeshPath(GetDefaultRightHandMeshPath());
const FString RightHandDefaultMeshPathOnly(GetDefaultRightHandMeshPathOnly());
if (CurrentMeshPath == LeftHandDefaultMeshPath
|| CurrentMeshPath == LeftHandDefaultMeshPathOnly
|| CurrentMeshPath == RightHandDefaultMeshPath
|| CurrentMeshPath == RightHandDefaultMeshPathOnly)
{
return false;
}
return true;
}
USkeletalMesh* USGVirtualHandMeshComponent::FImpl::LoadDefaultMesh() const
{
const FString SkeletalMeshPath(GetDefaultMeshPath());
USkeletalMesh* SkeletalMesh = Cast<USkeletalMesh>(
StaticLoadObject(USkeletalMesh::StaticClass(), nullptr, *SkeletalMeshPath));
ensureAlwaysMsgf(SkeletalMesh, TEXT("Failed to load the skeletal mesh: '%s'"), *SkeletalMeshPath);
return SkeletalMesh;
}
void USGVirtualHandMeshComponent::FImpl::SetDefaultMesh() const
{
Owner->SetSkeletalMesh(LoadDefaultMesh(), true);
}
USkeletalMesh* USGVirtualHandMeshComponent::FImpl::GetMesh() const
{
return Owner->
#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 1
GetSkeletalMeshAsset()
#else
SkeletalMesh
#endif /* ENGINE_MAJOR_VERSION == 5 && ENGINE_MINOR_VERSION >= 1 */
;
}
USkeleton* USGVirtualHandMeshComponent::FImpl::GetSkeleton() const
{
USkeletalMesh* SkeletalMesh{GetMesh()};
ensureAlwaysMsgf(IsValid(SkeletalMesh), TEXT("Invalid SkeletalMesh object!"));
return SkeletalMesh->
#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 1
GetSkeleton()
#else
Skeleton
#endif /* ENGINE_MAJOR_VERSION == 5 && ENGINE_MINOR_VERSION >= 1 */
;
}
const FReferenceSkeleton& USGVirtualHandMeshComponent::FImpl::GetRefSkeleton() const
{
USkeletalMesh* SkeletalMesh{GetMesh()};
ensureAlwaysMsgf(IsValid(SkeletalMesh), TEXT("Invalid SkeletalMesh object!"));
return SkeletalMesh->
#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 1
GetRefSkeleton()
#else
RefSkeleton
#endif /* ENGINE_MAJOR_VERSION == 5 && ENGINE_MINOR_VERSION >= 1 */
;
}
bool USGVirtualHandMeshComponent::FImpl::CheckGlove() const
{
const bool bGloveWasPresent = IsValid(Owner->Glove);
const bool bFoundGlove = USGHapticGlove::GetGlove(Owner, Owner->IsRight(), Owner->Glove);
if (!bFoundGlove && bGloveWasPresent)
{
SGLOG_ERROR(FString::Printf(TEXT("Could not find a %s glove"),
(Owner->bRight ? TEXT("right-handed") : TEXT("left-handed"))));
}
return bFoundGlove;
}
void USGVirtualHandMeshComponent::FImplDeleter::operator()(const FImpl* P) const
{
delete P;
}
@@ -0,0 +1,144 @@
/**
* @file
*
* @author Mamadou Babaei <mamadou@senseglove.com>
*
* @section LICENSE
*
* (The MIT License)
*
* Copyright (c) 2020 - 2023 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
*
*
*/
#pragma once
#include "Containers/Array.h"
#include "Components/SkeletalMeshComponent.h"
#include "Containers/Map.h"
#include "GameFramework/Actor.h"
#include "Math/Rotator.h"
#include "Math/Transform.h"
#include "ReferenceSkeleton.h"
#include "Templates/UniquePtr.h"
#include "UObject/NameTypes.h"
#include "SGVirtualHandMeshComponent.generated.h"
class USkeletalMesh;
class USkeleton;
class USceneComponent;
class USGHandPose;
class USGHapticGlove;
UCLASS(Config=Engine, Blueprintable, ClassGroup=(Rendering, Common), hidecategories=(Object, "Mesh|SkeletalAsset"),
editinlinenew, meta=(BlueprintSpawnableComponent))
class SENSEGLOVE_API USGVirtualHandMeshComponent : public USkeletalMeshComponent
{
GENERATED_UCLASS_BODY()
public:
static const TArray<TArray<FName>>& GetLeftHandFingerBoneNames();
static const TArray<TArray<FName>>& GetRightHandFingerBoneNames();
static const FName& GetLeftHandFingerBoneName(int32 Finger, int32 Joint);
static const FName& GetRightHandFingerBoneName(int32 Finger, int32 Joint);
private:
struct FImpl;
struct FImplDeleter
{
void operator()(const FImpl* P) const;
};
TUniquePtr<FImpl, FImplDeleter> Pimpl;
FImplDeleter PimplDeleter;
private:
UPROPERTY(EditAnywhere, Category="SenseGlove", meta=(AllowPrivateAccess="false"))
uint8 bRight : 1;
UPROPERTY(EditAnywhere, Category="SenseGlove", meta=(AllowPrivateAccess="false"))
uint8 bHiddenInGameIfNoGloveDetected : 1;
private:
UPROPERTY(Transient)
USGHapticGlove* Glove;
public:
FORCEINLINE bool IsLeft() const
{
return !IsRight();
}
FORCEINLINE bool IsRight() const
{
return !!bRight;
}
FORCEINLINE void SetRight(const bool bInRight)
{
bRight = bInRight;
}
FORCEINLINE bool IsHiddenInGameIfNoGloveDetected() const
{
return !!bHiddenInGameIfNoGloveDetected;
}
FORCEINLINE void SetHiddenIfNoGloveDetected(const bool bInHiddenIfNoGloveDetected)
{
bHiddenInGameIfNoGloveDetected = bInHiddenIfNoGloveDetected;
}
public:
virtual void SetAnimClass(class UClass* NewClass) override;
virtual void InitializeComponent() override;
virtual void TickComponent(float DeltaTime,
enum ELevelTick TickType,
FActorComponentTickFunction* ThisTickFunction) override;
virtual void SetSkeletalMesh(USkeletalMesh* NewMesh, bool bReinitPose = true) override;
protected:
virtual void EditorTick(float DeltaTime,
enum ELevelTick TickType,
FActorComponentTickFunction* ThisTickFunction);
public:
bool IsGloveConnected() const;
USGHandPose* GetHandPose();
public:
const FName& GetFingerBoneName(int32 Finger, int32 Joint) const;
const FTransform& GetFingerBoneRefTransform(int32 Finger, int32 Joint) const;
FRotator GetFingerBoneRefRotation(int32 Finger, int32 Joint) const;
TMap<FName, FRotator> GetFingersBonesRotations();
};
@@ -0,0 +1,129 @@
/**
* @file
*
* @author Mamadou Babaei <mamadou@senseglove.com>
*
* @section LICENSE
*
* (The MIT License)
*
* Copyright (c) 2020 - 2023 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 "SGKismet/SGVirtualHandMeshComponentKismetLibrary.h"
#include "SenseGlove/Components/SGVirtualHandMeshComponent.h"
#include "SGCore/SGHandPose.h"
#include "SGUtils/SGArrayUtils.h"
TArray<FSGNameArray> UVirtualHandMeshComponentKismetLibrary::GetLeftHandFingerBoneNames()
{
return FSGArrayUtils::ToNestedBPArray<FName, FSGNameArray>(
USGVirtualHandMeshComponent::GetLeftHandFingerBoneNames());
}
TArray<FSGNameArray> UVirtualHandMeshComponentKismetLibrary::GetRightHandFingerBoneNames()
{
return FSGArrayUtils::ToNestedBPArray<FName, FSGNameArray>(
USGVirtualHandMeshComponent::GetRightHandFingerBoneNames());
}
const FName& UVirtualHandMeshComponentKismetLibrary::GetLeftHandFingerBoneName(const int32 Finger, const int32 Joint)
{
return USGVirtualHandMeshComponent::GetLeftHandFingerBoneName(Finger, Joint);
}
const FName& UVirtualHandMeshComponentKismetLibrary::GetRightHandFingerBoneName(const int32 Finger, const int32 Joint)
{
return USGVirtualHandMeshComponent::GetRightHandFingerBoneName(Finger, Joint);
}
bool UVirtualHandMeshComponentKismetLibrary::IsLeft(const USGVirtualHandMeshComponent* VirtualHandMeshComponent)
{
return VirtualHandMeshComponent->IsLeft();
}
bool UVirtualHandMeshComponentKismetLibrary::IsRight(const USGVirtualHandMeshComponent* VirtualHandMeshComponent)
{
return VirtualHandMeshComponent->IsRight();
}
void UVirtualHandMeshComponentKismetLibrary::SetRight(USGVirtualHandMeshComponent* VirtualHandMeshComponent,
const bool bInRight)
{
VirtualHandMeshComponent->SetRight(bInRight);
}
bool UVirtualHandMeshComponentKismetLibrary::IsHiddenInGameIfNoGloveDetected(
const USGVirtualHandMeshComponent* VirtualHandMeshComponent)
{
return VirtualHandMeshComponent->IsHiddenInGameIfNoGloveDetected();
}
void UVirtualHandMeshComponentKismetLibrary::SetHiddenIfNoGloveDetected(
USGVirtualHandMeshComponent* VirtualHandMeshComponent,
const bool bInHiddenIfNoGloveDetected)
{
VirtualHandMeshComponent->SetHiddenIfNoGloveDetected(bInHiddenIfNoGloveDetected);
}
bool UVirtualHandMeshComponentKismetLibrary::IsGloveConnected(
const USGVirtualHandMeshComponent* VirtualHandMeshComponent) const
{
return VirtualHandMeshComponent->IsGloveConnected();
}
USGHandPose* UVirtualHandMeshComponentKismetLibrary::GetHandPose(USGVirtualHandMeshComponent* VirtualHandMeshComponent)
{
return VirtualHandMeshComponent->GetHandPose();
}
const FName& UVirtualHandMeshComponentKismetLibrary::GetFingerBoneName(
const USGVirtualHandMeshComponent* VirtualHandMeshComponent,
const int32 Finger, const int32 Joint) const
{
return VirtualHandMeshComponent->GetFingerBoneName(Finger, Joint);
}
const FTransform& UVirtualHandMeshComponentKismetLibrary::GetFingerBoneRefTransform(
const USGVirtualHandMeshComponent* VirtualHandMeshComponent,
const int32 Finger, const int32 Joint) const
{
return VirtualHandMeshComponent->GetFingerBoneRefTransform(Finger, Joint);
}
FRotator UVirtualHandMeshComponentKismetLibrary::GetFingerBoneRefRotation(
const USGVirtualHandMeshComponent* VirtualHandMeshComponent,
const int32 Finger, const int32 Joint) const
{
return VirtualHandMeshComponent->GetFingerBoneRefRotation(Finger, Joint);
}
TMap<FName, FRotator> UVirtualHandMeshComponentKismetLibrary::GetFingersBonesRotations(
USGVirtualHandMeshComponent* VirtualHandMeshComponent)
{
return VirtualHandMeshComponent->GetFingersBonesRotations();
}
@@ -0,0 +1,114 @@
/**
* @file
*
* @author Mamadou Babaei <mamadou@senseglove.com>
*
* @section LICENSE
*
* (The MIT License)
*
* Copyright (c) 2020 - 2023 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
*
* A data class containing the minimum required data for a hand's forward
* kinematics.
* Used in both kinematics and calibration.
*/
#pragma once
#include "Containers/Array.h"
#include "Containers/Map.h"
#include "GameFramework/Actor.h"
#include "Math/Rotator.h"
#include "Math/Transform.h"
#include "UObject/NameTypes.h"
#include "SGKismet/SGBlueprintFunctionLibrary.h"
#include "SGTypes/SGNameArray.h"
#include "SGVirtualHandMeshComponentKismetLibrary.generated.h"
class USkeletalMeshComponent;
class USGVirtualHandMeshComponent;
class USGHandPose;
/**
* Represents data of a user's hand required for forward kinematics.
*/
UCLASS(meta=(ScriptName = "SesneGloveVirtualHandMeshComponentKismetLibrary"))
class SENSEGLOVEKISMET_API UVirtualHandMeshComponentKismetLibrary final : public USGBlueprintFunctionLibrary
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintCallable, Category="SenseGlove | Components | Virtual Hand Mesh Component")
static TArray<FSGNameArray> GetLeftHandFingerBoneNames();
UFUNCTION(BlueprintCallable, Category="SenseGlove | Components | Virtual Hand Mesh Component")
static TArray<FSGNameArray> GetRightHandFingerBoneNames();
UFUNCTION(BlueprintCallable, Category="SenseGlove | Components | Virtual Hand Mesh Component")
static const FName& GetLeftHandFingerBoneName(int32 Finger, int32 Joint);
UFUNCTION(BlueprintCallable, Category="SenseGlove | Components | Virtual Hand Mesh Component")
static const FName& GetRightHandFingerBoneName(int32 Finger, int32 Joint);
UFUNCTION(BlueprintPure, Category="SenseGlove | Components | Virtual Hand Mesh Component")
static bool IsLeft(const USGVirtualHandMeshComponent* VirtualHandMeshComponent);
UFUNCTION(BlueprintPure, Category="SenseGlove | Components | Virtual Hand Mesh Component")
static bool IsRight(const USGVirtualHandMeshComponent* VirtualHandMeshComponent);
UFUNCTION(BlueprintCallable, Category="SenseGlove | Components | Virtual Hand Mesh Component")
static void SetRight(UPARAM(ref) USGVirtualHandMeshComponent* VirtualHandMeshComponent, bool bInRight);
UFUNCTION(BlueprintPure, Category="SenseGlove | Components | Virtual Hand Mesh Component")
static bool IsHiddenInGameIfNoGloveDetected(const USGVirtualHandMeshComponent* VirtualHandMeshComponent);
UFUNCTION(BlueprintCallable, Category="SenseGlove | Components | Virtual Hand Mesh Component")
static void SetHiddenIfNoGloveDetected(UPARAM(ref) USGVirtualHandMeshComponent* VirtualHandMeshComponent,
bool bInHiddenIfNoGloveDetected);
UFUNCTION(BlueprintPure, Category="SenseGlove | Components | Virtual Hand Mesh Component")
bool IsGloveConnected(const USGVirtualHandMeshComponent* VirtualHandMeshComponent) const;
UFUNCTION(BlueprintCallable, Category="SenseGlove | Components | Virtual Hand Mesh Component")
USGHandPose* GetHandPose(UPARAM(ref) USGVirtualHandMeshComponent* VirtualHandMeshComponent);
UFUNCTION(BlueprintPure, Category="SenseGlove | Components | Virtual Hand Mesh Component")
const FName& GetFingerBoneName(const USGVirtualHandMeshComponent* VirtualHandMeshComponent,
int32 Finger, int32 Joint) const;
UFUNCTION(BlueprintPure, Category="SenseGlove | Components | Virtual Hand Mesh Component")
const FTransform& GetFingerBoneRefTransform(const USGVirtualHandMeshComponent* VirtualHandMeshComponent,
int32 Finger, int32 Joint) const;
UFUNCTION(BlueprintPure, Category="SenseGlove | Components | Virtual Hand Mesh Component")
FRotator GetFingerBoneRefRotation(const USGVirtualHandMeshComponent* VirtualHandMeshComponent,
int32 Finger, int32 Joint) const;
UFUNCTION(BlueprintCallable, Category="SenseGlove | Components | Virtual Hand Mesh Component")
TMap<FName, FRotator> GetFingersBonesRotations(UPARAM(ref) USGVirtualHandMeshComponent* VirtualHandMeshComponent);
};