add partion implementation of the virtual hand
This commit is contained in:
@@ -1,36 +0,0 @@
|
||||
/**
|
||||
* @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/Animation/SGAnimInstanceProxy.h"
|
||||
+25
-5
@@ -33,20 +33,40 @@
|
||||
*/
|
||||
|
||||
|
||||
#include "SenseGlove/Animation/SGAnimInstance.h"
|
||||
#include "SenseGlove/Animation/SGVirtualHandAnimInstance.h"
|
||||
|
||||
USGAnimInstance::USGAnimInstance(const FObjectInitializer& ObjectInitializer)
|
||||
USGVirtualHandAnimInstance::USGVirtualHandAnimInstance(const FObjectInitializer& ObjectInitializer)
|
||||
: Super(ObjectInitializer)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void USGAnimInstance::NativeInitializeAnimation()
|
||||
void USGVirtualHandAnimInstance::NativeInitializeAnimation()
|
||||
{
|
||||
Super::NativeInitializeAnimation();
|
||||
}
|
||||
|
||||
FSGAnimInstanceProxy* USGAnimInstance::CreateAnimInstanceProxy()
|
||||
void USGVirtualHandAnimInstance::NativeUpdateAnimation(const float DeltaSeconds)
|
||||
{
|
||||
return new FSGAnimInstanceProxy();
|
||||
Super::NativeUpdateAnimation(DeltaSeconds);
|
||||
}
|
||||
|
||||
void USGVirtualHandAnimInstance::NativePostEvaluateAnimation()
|
||||
{
|
||||
Super::NativePostEvaluateAnimation();
|
||||
}
|
||||
|
||||
void USGVirtualHandAnimInstance::NativeUninitializeAnimation()
|
||||
{
|
||||
Super::NativeUninitializeAnimation();
|
||||
}
|
||||
|
||||
void USGVirtualHandAnimInstance::NativeBeginPlay()
|
||||
{
|
||||
Super::NativeBeginPlay();
|
||||
}
|
||||
|
||||
FSGVirtualHandAnimInstanceProxy* USGVirtualHandAnimInstance::CreateAnimInstanceProxy()
|
||||
{
|
||||
return new FSGVirtualHandAnimInstanceProxy();
|
||||
}
|
||||
+37
-3
@@ -33,10 +33,44 @@
|
||||
*/
|
||||
|
||||
|
||||
#include "SenseGlove/GameFramework/SGCharacter.h"
|
||||
#include "SenseGlove/Animation/SGVirtualHandAnimInstanceProxy.h"
|
||||
|
||||
ASGCharacter::ASGCharacter(const FObjectInitializer& ObjectInitializer)
|
||||
: Super(ObjectInitializer)
|
||||
void FSGVirtualHandAnimInstanceProxy::Initialize(UAnimInstance* InAnimInstance)
|
||||
{
|
||||
FAnimInstanceProxy::Initialize(InAnimInstance);
|
||||
}
|
||||
|
||||
void FSGVirtualHandAnimInstanceProxy::Uninitialize(UAnimInstance* InAnimInstance)
|
||||
{
|
||||
FAnimInstanceProxy::Uninitialize(InAnimInstance);
|
||||
}
|
||||
|
||||
void FSGVirtualHandAnimInstanceProxy::PreUpdate(UAnimInstance* InAnimInstance, const float DeltaSeconds)
|
||||
{
|
||||
FAnimInstanceProxy::PreUpdate(InAnimInstance, DeltaSeconds);
|
||||
}
|
||||
|
||||
void FSGVirtualHandAnimInstanceProxy::Update(const float DeltaSeconds)
|
||||
{
|
||||
FAnimInstanceProxy::Update(DeltaSeconds);
|
||||
}
|
||||
|
||||
void FSGVirtualHandAnimInstanceProxy::PreEvaluateAnimation(UAnimInstance* InAnimInstance)
|
||||
{
|
||||
FAnimInstanceProxy::PreEvaluateAnimation(InAnimInstance);
|
||||
}
|
||||
|
||||
bool FSGVirtualHandAnimInstanceProxy::Evaluate(FPoseContext& Output)
|
||||
{
|
||||
return FAnimInstanceProxy::Evaluate(Output);
|
||||
}
|
||||
|
||||
void FSGVirtualHandAnimInstanceProxy::PostUpdate(UAnimInstance* InAnimInstance) const
|
||||
{
|
||||
FAnimInstanceProxy::PostUpdate(InAnimInstance);
|
||||
}
|
||||
|
||||
void FSGVirtualHandAnimInstanceProxy::PostEvaluate(UAnimInstance* InAnimInstance)
|
||||
{
|
||||
FAnimInstanceProxy::PostEvaluate(InAnimInstance);
|
||||
}
|
||||
@@ -35,12 +35,12 @@
|
||||
|
||||
#include "SenseGlove/GameFramework//SGGameModeBase.h"
|
||||
|
||||
#include "SenseGlove/GameFramework/SGCharacter.h"
|
||||
#include "SenseGlove/GameFramework/SGPawn.h"
|
||||
#include "SenseGlove/GameFramework/SGPlayerController.h"
|
||||
|
||||
ASGGameModeBase::ASGGameModeBase(const FObjectInitializer& ObjectInitializer)
|
||||
: Super(ObjectInitializer)
|
||||
{
|
||||
DefaultPawnClass = ASGCharacter::StaticClass();
|
||||
DefaultPawnClass = ASGPawn::StaticClass();
|
||||
PlayerControllerClass = ASGPlayerController::StaticClass();
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
/**
|
||||
* @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/GameFramework/SGPawn.h"
|
||||
|
||||
#include "Components/ActorComponent.h"
|
||||
|
||||
#include "SenseGlove/GameFramework/SGPawn.h"
|
||||
|
||||
struct ASGPawn::FImpl
|
||||
{
|
||||
/************************
|
||||
* Static methods
|
||||
************************/
|
||||
|
||||
/************************
|
||||
* Owner object
|
||||
************************/
|
||||
|
||||
ASGPawn* Owner;
|
||||
|
||||
/************************
|
||||
* Constructor / Destructor
|
||||
************************/
|
||||
|
||||
explicit FImpl(ASGPawn* InOwner);
|
||||
~FImpl();
|
||||
|
||||
/************************
|
||||
* Default copy constructor & copy assignment operator
|
||||
************************/
|
||||
|
||||
FImpl(const FImpl& Rhs) = default;
|
||||
FImpl& operator=(const FImpl& Rhs) = default;
|
||||
|
||||
/************************
|
||||
* Methods
|
||||
************************/
|
||||
|
||||
};
|
||||
|
||||
ASGPawn::ASGPawn(const FObjectInitializer& ObjectInitializer)
|
||||
: Super(ObjectInitializer),
|
||||
#if ENGINE_MAJOR_VERSION == 5 || ( ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION > 24 )
|
||||
Pimpl(TUniquePtr<FImpl, FImplDeleter>(new FImpl{this}, PimplDeleter))
|
||||
#else
|
||||
Pimpl(TUniquePtr<FImpl, FImplDeleter>(new FImpl{this}))
|
||||
#endif /* ENGINE_MAJOR_VERSION == 5 || ( ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION > 24 ) */
|
||||
{
|
||||
PrimaryActorTick.bCanEverTick = true;
|
||||
|
||||
SceneRoot = CreateDefaultSubobject<USceneComponent>(TEXT("SceneRoot"));
|
||||
SetRootComponent(SceneRoot);
|
||||
}
|
||||
|
||||
ASGPawn::FImpl::FImpl(ASGPawn* InOwner)
|
||||
: Owner(InOwner)
|
||||
{
|
||||
}
|
||||
|
||||
ASGPawn::FImpl::~FImpl() = default;
|
||||
|
||||
void ASGPawn::FImplDeleter::operator()(const FImpl* P) const
|
||||
{
|
||||
delete P;
|
||||
}
|
||||
@@ -0,0 +1,333 @@
|
||||
/**
|
||||
* @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/GameFramework/SGVirtualHand.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 ASGVirtualHand::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
|
||||
************************/
|
||||
|
||||
ASGVirtualHand* Owner;
|
||||
|
||||
/************************
|
||||
* Constructor / Destructor
|
||||
************************/
|
||||
|
||||
explicit FImpl(ASGVirtualHand* InOwner);
|
||||
~FImpl();
|
||||
|
||||
/************************
|
||||
* Default copy constructor & copy assignment operator
|
||||
************************/
|
||||
|
||||
FImpl(const FImpl& Rhs) = default;
|
||||
FImpl& operator=(const FImpl& Rhs) = default;
|
||||
|
||||
/************************
|
||||
* Methods
|
||||
************************/
|
||||
|
||||
bool IsEditor() const;
|
||||
|
||||
void SetHandMesh(USkeletalMesh* VirtualHandMesh, bool bReinitPos) const;
|
||||
|
||||
FString GetDefaultMeshPath() const;
|
||||
bool IsUsingUserMesh() const;
|
||||
USkeletalMesh* LoadDefaultMesh() const;
|
||||
void SetDefaultMesh() const;
|
||||
|
||||
bool CheckGlove() const;
|
||||
};
|
||||
|
||||
ASGVirtualHand::ASGVirtualHand(const FObjectInitializer& ObjectInitializer)
|
||||
: Super(ObjectInitializer),
|
||||
#if ENGINE_MAJOR_VERSION == 5 || ( ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION > 24 )
|
||||
Pimpl(TUniquePtr<FImpl, FImplDeleter>(new FImpl{this}, PimplDeleter))
|
||||
#else
|
||||
Pimpl(TUniquePtr<FImpl, FImplDeleter>(new FImpl{this}))
|
||||
#endif /* ENGINE_MAJOR_VERSION == 5 || ( ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION > 24 ) */
|
||||
{
|
||||
PrimaryActorTick.bCanEverTick = true;
|
||||
|
||||
SceneRoot = CreateDefaultSubobject<USceneComponent>(TEXT("SceneRoot"));
|
||||
SetRootComponent(SceneRoot);
|
||||
|
||||
Mesh = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("Mesh"));
|
||||
Mesh->SetupAttachment(RootComponent);
|
||||
Mesh->SetCastShadow(true);
|
||||
Mesh->SetCastHiddenShadow(false);
|
||||
Mesh->bCastDynamicShadow = true;
|
||||
Mesh->SetOnlyOwnerSee(false);
|
||||
Mesh->SetReceivesDecals(true);
|
||||
Mesh->SetCanEverAffectNavigation(false);
|
||||
Mesh->SetCollisionObjectType(ECC_WorldDynamic);
|
||||
Mesh->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);
|
||||
Mesh->SetCollisionResponseToAllChannels(ECR_Overlap);
|
||||
Mesh->SetCollisionResponseToChannel(ECC_WorldStatic, ECR_Block);
|
||||
Mesh->SetCollisionResponseToChannel(ECC_WorldDynamic, ECR_Block);
|
||||
Mesh->SetCollisionResponseToChannel(ECC_Pawn, ECR_Block);
|
||||
Mesh->SetCollisionResponseToChannel(ECC_Visibility, ECR_Block);
|
||||
Mesh->SetCollisionResponseToChannel(ECC_PhysicsBody, ECR_Block);
|
||||
Mesh->SetCollisionResponseToChannel(ECC_Vehicle, ECR_Block);
|
||||
Mesh->SetCollisionResponseToChannel(ECC_Destructible, ECR_Block);
|
||||
|
||||
AnimInstanceClass = USGVirtualHandAnimInstance::StaticClass();
|
||||
|
||||
bRight = true;
|
||||
bHiddenInGameIfNoGloveDetected = true;
|
||||
bAnimateInEditor = 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);
|
||||
Pimpl->SetHandMesh(SkeletalMesh.Object, true);
|
||||
|
||||
Glove = nullptr;
|
||||
}
|
||||
|
||||
void ASGVirtualHand::SetHandMesh(USkeletalMesh* VirtualHandMesh, const bool bReinitPos) const
|
||||
{
|
||||
Pimpl->SetHandMesh(VirtualHandMesh, bReinitPos);
|
||||
}
|
||||
|
||||
void ASGVirtualHand::Tick(const float DeltaSeconds)
|
||||
{
|
||||
#if WITH_EDITOR
|
||||
if (Pimpl->IsEditor())
|
||||
{
|
||||
EditorTick(DeltaSeconds);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
Super::Tick(DeltaSeconds);
|
||||
|
||||
(void)Pimpl->CheckGlove();
|
||||
}
|
||||
|
||||
bool ASGVirtualHand::ShouldTickIfViewportsOnly() const
|
||||
{
|
||||
if (!bAnimateInEditor)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Pimpl->IsEditor())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ASGVirtualHand::OnConstruction(const FTransform& Transform)
|
||||
{
|
||||
Super::OnConstruction(Transform);
|
||||
|
||||
if (!Pimpl->IsUsingUserMesh())
|
||||
{
|
||||
Pimpl->SetDefaultMesh();
|
||||
}
|
||||
}
|
||||
|
||||
void ASGVirtualHand::EditorTick(float DeltaSeconds)
|
||||
{
|
||||
(void)Pimpl->CheckGlove();
|
||||
}
|
||||
|
||||
bool ASGVirtualHand::IsGloveConnected()
|
||||
{
|
||||
return Pimpl->CheckGlove();
|
||||
}
|
||||
|
||||
USGHandPose* ASGVirtualHand::GetHandPose()
|
||||
{
|
||||
USGHandPose* HandPose = nullptr;
|
||||
|
||||
if (IsValid(Glove))
|
||||
{
|
||||
Glove->GetHandPose(this, HandPose);
|
||||
}
|
||||
|
||||
return HandPose;
|
||||
}
|
||||
|
||||
ASGVirtualHand::FImpl::FImpl(ASGVirtualHand* InOwner)
|
||||
: Owner(InOwner)
|
||||
{
|
||||
}
|
||||
|
||||
ASGVirtualHand::FImpl::~FImpl() = default;
|
||||
|
||||
void ASGVirtualHand::FImpl::SetHandMesh(USkeletalMesh* VirtualHandMesh, const bool bReinitPos) const
|
||||
{
|
||||
ensureAlwaysMsgf(IsValid(VirtualHandMesh), TEXT("Invalid VirtualHandMesh object!"));
|
||||
ensureAlwaysMsgf(IsValid(Owner->Mesh), TEXT("Invalid Mesh object!"));
|
||||
ensureAlwaysMsgf(IsValid(Owner->AnimInstanceClass), TEXT("Invalid AnimInstanceClass object!"));
|
||||
|
||||
Owner->Mesh->SetSkeletalMesh(VirtualHandMesh, bReinitPos);
|
||||
Owner->Mesh->SetAnimInstanceClass(Owner->AnimInstanceClass);
|
||||
}
|
||||
|
||||
bool ASGVirtualHand::FImpl::IsEditor() const
|
||||
{
|
||||
const UWorld* World = Owner->GetWorld();
|
||||
if (World && World->WorldType == EWorldType::Editor)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
FString ASGVirtualHand::FImpl::GetDefaultMeshPath() const
|
||||
{
|
||||
FString SkeletalMeshPath;
|
||||
|
||||
if (Owner->bRight)
|
||||
{
|
||||
SkeletalMeshPath = GetDefaultRightHandMeshPath();
|
||||
}
|
||||
else
|
||||
{
|
||||
SkeletalMeshPath = GetDefaultLeftHandMeshPath();
|
||||
}
|
||||
|
||||
return SkeletalMeshPath;
|
||||
}
|
||||
|
||||
bool ASGVirtualHand::FImpl::IsUsingUserMesh() const
|
||||
{
|
||||
ensureAlwaysMsgf(IsValid(Owner->Mesh), TEXT("Invalid Mesh object!"));
|
||||
|
||||
if (!IsValid(Owner->Mesh->SkeletalMesh))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const FString CurrentMeshPath(Owner->Mesh->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* ASGVirtualHand::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 ASGVirtualHand::FImpl::SetDefaultMesh() const
|
||||
{
|
||||
SetHandMesh(LoadDefaultMesh(), true);
|
||||
}
|
||||
|
||||
bool ASGVirtualHand::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 ASGVirtualHand::FImplDeleter::operator()(const FImpl* P) const
|
||||
{
|
||||
delete P;
|
||||
}
|
||||
+20
-5
@@ -37,18 +37,33 @@
|
||||
|
||||
#include "Animation/AnimInstance.h"
|
||||
|
||||
#include "SenseGlove/Animation/SGAnimInstanceProxy.h"
|
||||
#include "SenseGlove/Animation/SGVirtualHandAnimInstanceProxy.h"
|
||||
|
||||
#include "SGAnimInstance.generated.h"
|
||||
#include "SGVirtualHandAnimInstance.generated.h"
|
||||
|
||||
UCLASS(Transient, Blueprintable, HideCategories=SGAnimInstance, BlueprintType, Meta=(BlueprintThreadSafe), Within=SkeletalMeshComponent)
|
||||
class SENSEGLOVE_API USGAnimInstance : public UAnimInstance
|
||||
UCLASS(Transient, Blueprintable, BlueprintType, meta=(BlueprintThreadSafe), Within=SkeletalMeshComponent)
|
||||
class SENSEGLOVE_API USGVirtualHandAnimInstance : public UAnimInstance
|
||||
{
|
||||
GENERATED_UCLASS_BODY()
|
||||
|
||||
public:
|
||||
// the below functions are the native overrides for each phase
|
||||
// Native initialization override point
|
||||
virtual void NativeInitializeAnimation() override;
|
||||
|
||||
// Native update override point. It is usually a good idea to simply gather data in this step and
|
||||
// for the bulk of the work to be done in NativeUpdateAnimation.
|
||||
virtual void NativeUpdateAnimation(float DeltaSeconds) override;
|
||||
|
||||
// Native Post Evaluate override point
|
||||
virtual void NativePostEvaluateAnimation() override;
|
||||
|
||||
// Native Uninitialize override point
|
||||
virtual void NativeUninitializeAnimation() override;
|
||||
|
||||
// Executed when begin play is called on the owning component
|
||||
virtual void NativeBeginPlay() override;
|
||||
|
||||
protected:
|
||||
virtual FSGAnimInstanceProxy* CreateAnimInstanceProxy() override;
|
||||
virtual FSGVirtualHandAnimInstanceProxy* CreateAnimInstanceProxy() override;
|
||||
};
|
||||
+31
-2
@@ -37,10 +37,39 @@
|
||||
|
||||
#include "Animation/AnimInstanceProxy.h"
|
||||
|
||||
#include "SGAnimInstanceProxy.generated.h"
|
||||
#include "SGVirtualHandAnimInstanceProxy.generated.h"
|
||||
|
||||
USTRUCT()
|
||||
struct SENSEGLOVE_API FSGAnimInstanceProxy : public FAnimInstanceProxy
|
||||
struct SENSEGLOVE_API FSGVirtualHandAnimInstanceProxy : public FAnimInstanceProxy
|
||||
{
|
||||
GENERATED_USTRUCT_BODY()
|
||||
|
||||
protected:
|
||||
/** Called when our anim instance is being initialized */
|
||||
virtual void Initialize(UAnimInstance* InAnimInstance) override;
|
||||
|
||||
/** Called when our anim instance is being uninitialized */
|
||||
virtual void Uninitialize(UAnimInstance* InAnimInstance) override;
|
||||
|
||||
/** Called before update so we can copy any data we need */
|
||||
virtual void PreUpdate(UAnimInstance* InAnimInstance, float DeltaSeconds) override;
|
||||
|
||||
/** Update override point */
|
||||
virtual void Update(float DeltaSeconds) override;
|
||||
|
||||
/** Called on the game thread pre-evaluate. */
|
||||
virtual void PreEvaluateAnimation(UAnimInstance* InAnimInstance) override;
|
||||
|
||||
/**
|
||||
* Evaluate override point
|
||||
* @return true if this function is implemented, false otherwise.
|
||||
* Note: the node graph will not be evaluated if this function returns true
|
||||
*/
|
||||
virtual bool Evaluate(FPoseContext& Output) override;
|
||||
|
||||
/** Called after update so we can copy any data we need */
|
||||
virtual void PostUpdate(UAnimInstance* InAnimInstance) const override;
|
||||
|
||||
/** Called after evaluate so we can do any game thread work we need to */
|
||||
virtual void PostEvaluate(UAnimInstance* InAnimInstance) override;
|
||||
};
|
||||
@@ -1,46 +0,0 @@
|
||||
/**
|
||||
* @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 "GameFramework/Character.h"
|
||||
|
||||
#include "SGCharacter.generated.h"
|
||||
|
||||
UCLASS(Config=Game, BlueprintType)
|
||||
class SENSEGLOVE_API ASGCharacter : public ACharacter
|
||||
{
|
||||
GENERATED_UCLASS_BODY()
|
||||
};
|
||||
@@ -0,0 +1,98 @@
|
||||
/**
|
||||
* @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 "GameFramework/Pawn.h"
|
||||
#include "Templates/UniquePtr.h"
|
||||
|
||||
#include "SGPawn.generated.h"
|
||||
|
||||
class UActorComponent;
|
||||
class UMotionControllerComponent;
|
||||
|
||||
UCLASS(Config=Game, BlueprintType, Blueprintable)
|
||||
class SENSEGLOVE_API ASGPawn : public APawn
|
||||
{
|
||||
GENERATED_UCLASS_BODY()
|
||||
|
||||
private:
|
||||
struct FImpl;
|
||||
|
||||
struct FImplDeleter
|
||||
{
|
||||
void operator()(const FImpl* P) const;
|
||||
};
|
||||
|
||||
TUniquePtr<FImpl, FImplDeleter> Pimpl;
|
||||
FImplDeleter PimplDeleter;
|
||||
|
||||
private:
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="SenseGlove", meta=(AllowPrivateAccess="true"))
|
||||
USceneComponent* SceneRoot;
|
||||
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="SenseGlove", meta=(AllowPrivateAccess="true"))
|
||||
UMotionControllerComponent* MotionControllerLeft;
|
||||
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="SenseGlove", meta=(AllowPrivateAccess="true"))
|
||||
UMotionControllerComponent* MotionControllerRight;
|
||||
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="SenseGlove", meta=(AllowPrivateAccess="true"))
|
||||
UActorComponent* HandLeft;
|
||||
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="SenseGlove", meta=(AllowPrivateAccess="true"))
|
||||
UActorComponent* HandRight;
|
||||
|
||||
protected:
|
||||
FORCEINLINE UMotionControllerComponent* GetMotionContollerLeft() const
|
||||
{
|
||||
return MotionControllerLeft;
|
||||
}
|
||||
|
||||
FORCEINLINE UMotionControllerComponent* GetMotionContollerRight() const
|
||||
{
|
||||
return MotionControllerRight;
|
||||
}
|
||||
|
||||
FORCEINLINE UActorComponent* GetHandLeft() const
|
||||
{
|
||||
return HandLeft;
|
||||
}
|
||||
|
||||
FORCEINLINE UActorComponent* GetHandRight() const
|
||||
{
|
||||
return HandRight;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,162 @@
|
||||
/**
|
||||
* @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 "GameFramework/Actor.h"
|
||||
#include "Templates/UniquePtr.h"
|
||||
|
||||
#include "SGVirtualHand.generated.h"
|
||||
|
||||
class USkeletalMesh;
|
||||
class USkeletalMeshComponent;
|
||||
class USceneComponent;
|
||||
|
||||
class USGHandPose;
|
||||
class USGHapticGlove;
|
||||
|
||||
UCLASS(Config=Game, BlueprintType)
|
||||
class SENSEGLOVE_API ASGVirtualHand : public AActor
|
||||
{
|
||||
GENERATED_UCLASS_BODY()
|
||||
|
||||
private:
|
||||
struct FImpl;
|
||||
|
||||
struct FImplDeleter
|
||||
{
|
||||
void operator()(const FImpl* P) const;
|
||||
};
|
||||
|
||||
TUniquePtr<FImpl, FImplDeleter> Pimpl;
|
||||
FImplDeleter PimplDeleter;
|
||||
|
||||
private:
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="SenseGlove", meta=(AllowPrivateAccess="true"))
|
||||
USceneComponent* SceneRoot;
|
||||
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category="SenseGlove", meta=(AllowPrivateAccess="true"))
|
||||
USkeletalMeshComponent* Mesh;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="SenseGlove", meta=(AllowPrivateAccess="true"))
|
||||
UClass* AnimInstanceClass;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="SenseGlove", meta=(AllowPrivateAccess="true"))
|
||||
uint8 bRight : 1;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="SenseGlove", meta=(AllowPrivateAccess="true"))
|
||||
uint8 bHiddenInGameIfNoGloveDetected : 1;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="SenseGlove", meta=(AllowPrivateAccess="true"))
|
||||
uint8 bAnimateInEditor : 1;
|
||||
|
||||
private:
|
||||
UPROPERTY(Transient)
|
||||
USGHapticGlove* Glove;
|
||||
|
||||
public:
|
||||
FORCEINLINE USkeletalMeshComponent* GetMesh() const
|
||||
{
|
||||
return Mesh;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
FORCEINLINE bool IsAnimateInEditor() const
|
||||
{
|
||||
return bAnimateInEditor;
|
||||
}
|
||||
|
||||
FORCEINLINE void SetAnimateInEditor(const bool bInAnimateInEditor)
|
||||
{
|
||||
bAnimateInEditor = bInAnimateInEditor;
|
||||
}
|
||||
|
||||
void SetHandMesh(USkeletalMesh* VirtualHandMesh, bool bReinitPos) const;
|
||||
|
||||
protected:
|
||||
FORCEINLINE void SetMesh(USkeletalMeshComponent* InMesh)
|
||||
{
|
||||
Mesh = InMesh;
|
||||
}
|
||||
|
||||
FORCEINLINE UClass* GetAnimInstanceClass() const
|
||||
{
|
||||
return AnimInstanceClass;
|
||||
}
|
||||
|
||||
FORCEINLINE void SetAnimInstanceClass(UClass* InAnimInstanceClass)
|
||||
{
|
||||
AnimInstanceClass = InAnimInstanceClass;
|
||||
}
|
||||
|
||||
public:
|
||||
virtual void Tick(float DeltaSeconds) override;
|
||||
|
||||
virtual bool ShouldTickIfViewportsOnly() const override;
|
||||
|
||||
virtual void OnConstruction(const FTransform& Transform) override;
|
||||
|
||||
protected:
|
||||
virtual void EditorTick(float DeltaSeconds);
|
||||
|
||||
public:
|
||||
bool IsGloveConnected();
|
||||
USGHandPose* GetHandPose();
|
||||
};
|
||||
@@ -54,6 +54,7 @@ public class SenseGlove : ModuleRules
|
||||
{
|
||||
"CoreUObject",
|
||||
"Engine",
|
||||
"HeadMountedDisplay",
|
||||
"SenseGloveConnect",
|
||||
"SenseGloveCore",
|
||||
"SenseGloveLog",
|
||||
|
||||
Reference in New Issue
Block a user