add the initial implementation for the touch functionality and its feedbacks

This commit is contained in:
Mamadou Babaei
2023-05-19 18:13:47 +02:00
parent 88033a2df1
commit e4361cffc3
2 changed files with 266 additions and 3 deletions
@@ -35,12 +35,263 @@
#include "SenseGlove/GameFramework/SGPlayerController.h"
#include "Engine/TimerHandle.h"
#include "TimerManager.h"
#include "SenseGlove/Components/SGGrabComponent.h"
#include "SenseGlove/Components/SGTouchComponent.h"
#include "SenseGlove/GameFramework/SGPawn.h"
#include "SGCore/SGBuzzCommand.h"
#include "SGCore/SGForceFeedbackCommand.h"
#include "SGCore/SGHapticGlove.h"
struct ASGPlayerController::FImpl
{
/************************
* Static methods
************************/
static int32 GetBuzzLevel(const AActor* Actor);
static float GetBuzzDuration(const AActor* ActorThumbTouching, const AActor* ActorIndexTouching,
const AActor* ActorMiddleTouching, const AActor* ActorRingTouching,
const AActor* ActorPinkyTouching);
static int32 GetForceFeedbackLevel(const AActor* Actor);
/************************
* Member variables
************************/
FTimerHandle TouchBuzzStopTimer;
/************************
* Owner object
************************/
ASGPlayerController* Owner;
/************************
* Constructor / Destructor
************************/
explicit FImpl(ASGPlayerController* InOwner);
~FImpl();
/************************
* Default copy constructor & copy assignment operator
************************/
FImpl(const FImpl& Rhs) = default;
FImpl& operator=(const FImpl& Rhs) = default;
/************************
* Methods
************************/
USGBuzzCommand* GetBuzzCommand(const AActor* ActorThumbTouching, const AActor* ActorIndexTouching,
const AActor* ActorMiddleTouching, const AActor* ActorRingTouching,
const AActor* ActorPinkyTouching) const;
USGForceFeedbackCommand* GetForceFeedbackCommand(const AActor* ActorThumbTouching, const AActor* ActorIndexTouching,
const AActor* ActorMiddleTouching, const AActor* ActorRingTouching,
const AActor* ActorPinkyTouching) const;
};
int32 ASGPlayerController::FImpl::GetBuzzLevel(const AActor* Actor)
{
if (IsValid(Actor))
{
const USGTouchComponent* TouchComponent = USGTouchComponent::GetTouchComponent(Actor);
if (TouchComponent)
{
return TouchComponent->GetBuzzLevel();
}
}
return 0;
}
float ASGPlayerController::FImpl::GetBuzzDuration(const AActor* ActorThumbTouching, const AActor* ActorIndexTouching,
const AActor* ActorMiddleTouching, const AActor* ActorRingTouching,
const AActor* ActorPinkyTouching)
{
if (IsValid(ActorThumbTouching))
{
const USGTouchComponent* TouchComponent = USGTouchComponent::GetTouchComponent(ActorThumbTouching);
if (TouchComponent)
{
return TouchComponent->GetBuzzDuration();
}
}
if (IsValid(ActorIndexTouching))
{
const USGTouchComponent* TouchComponent = USGTouchComponent::GetTouchComponent(ActorIndexTouching);
if (TouchComponent)
{
return TouchComponent->GetBuzzDuration();
}
}
if (IsValid(ActorMiddleTouching))
{
const USGTouchComponent* TouchComponent = USGTouchComponent::GetTouchComponent(ActorMiddleTouching);
if (TouchComponent)
{
return TouchComponent->GetBuzzDuration();
}
}
if (IsValid(ActorRingTouching))
{
const USGTouchComponent* TouchComponent = USGTouchComponent::GetTouchComponent(ActorRingTouching);
if (TouchComponent)
{
return TouchComponent->GetBuzzDuration();
}
}
if (IsValid(ActorPinkyTouching))
{
const USGTouchComponent* TouchComponent = USGTouchComponent::GetTouchComponent(ActorPinkyTouching);
if (TouchComponent)
{
return TouchComponent->GetBuzzDuration();
}
}
return 0.0f;
}
int32 ASGPlayerController::FImpl::GetForceFeedbackLevel(const AActor* Actor)
{
if (IsValid(Actor))
{
const USGTouchComponent* TouchComponent = USGTouchComponent::GetTouchComponent(Actor);
if (TouchComponent)
{
return TouchComponent->GetForceFeedbackLevel();
}
}
return 0;
}
ASGPlayerController::ASGPlayerController(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
}
void ASGPlayerController::SetupInputComponent()
void ASGPlayerController::BeginPlay()
{
Super::SetupInputComponent();
Super::BeginPlay();
ASGPawn* SGPawn = Cast<ASGPawn>(GetPawn());
if (ensureAlwaysMsgf(IsValid(SGPawn), TEXT("%s"), TEXT("ERROR: invalid SenseGlove pawn!")))
{
return;
}
SGPawn->OnGrabStateUpdated().AddWeakLambda(
this, [&](
const USGVirtualHandComponent* Hand,
const AActor* ActorThumbCanGrab, const AActor* ActorIndexCanGrab,
const AActor* ActorMiddleCanGrab) -> void
{
if (!IsValid(Hand))
{
return;
}
if (IsValid(ActorThumbCanGrab) &&
((ActorIndexCanGrab == ActorThumbCanGrab)) || ActorMiddleCanGrab == ActorThumbCanGrab)
{
}
});
SGPawn->OnTouchStateUpdated().AddWeakLambda(
this, [&](
const USGVirtualHandComponent* Hand,
const AActor* ActorThumbTouching, const AActor* ActorIndexTouching, const AActor* ActorMiddleTouching,
const AActor* ActorRingTouching, const AActor* ActorPinkyTouching) -> void
{
if (!IsValid(Hand))
{
return;
}
USGHapticGlove* Glove = Hand->GetConnectedGlove();
if (!IsValid(Glove))
{
return;
}
const USGBuzzCommand* BuzzCommand{Pimpl->GetBuzzCommand(
ActorThumbTouching, ActorIndexTouching, ActorMiddleTouching, ActorRingTouching, ActorPinkyTouching)};
Glove->SendHaptics(BuzzCommand);
const float Duration = FImpl::GetBuzzDuration(
ActorThumbTouching, ActorIndexTouching, ActorMiddleTouching, ActorRingTouching, ActorPinkyTouching);
GetWorldTimerManager().ClearTimer(Pimpl->TouchBuzzStopTimer);
FTimerDelegate TouchBuzzStopHandler;
TouchBuzzStopHandler.BindLambda([&]()-> void
{
Glove->SendHaptics(USGBuzzCommand::Off(this));
});
GetWorldTimerManager().SetTimer(
Pimpl->TouchBuzzStopTimer, TouchBuzzStopHandler, Duration, false, -1.0f);
const USGForceFeedbackCommand* ForceFeedbackCommand{Pimpl->GetForceFeedbackCommand(
ActorThumbTouching, ActorIndexTouching, ActorMiddleTouching, ActorRingTouching, ActorPinkyTouching)};
Glove->SendHaptics(ForceFeedbackCommand);
});
}
ASGPlayerController::FImpl::FImpl(ASGPlayerController* InOwner)
: Owner(InOwner)
{
}
ASGPlayerController::FImpl::~FImpl() = default;
USGBuzzCommand* ASGPlayerController::FImpl::GetBuzzCommand(const AActor* ActorThumbTouching,
const AActor* ActorIndexTouching,
const AActor* ActorMiddleTouching,
const AActor* ActorRingTouching,
const AActor* ActorPinkyTouching) const
{
USGBuzzCommand* BuzzCommand = USGBuzzCommand::NewBuzzCommand(
Owner,
GetBuzzLevel(ActorThumbTouching),
GetBuzzLevel(ActorIndexTouching),
GetBuzzLevel(ActorMiddleTouching),
GetBuzzLevel(ActorRingTouching),
GetBuzzLevel(ActorPinkyTouching)
);
return BuzzCommand;
}
USGForceFeedbackCommand* ASGPlayerController::FImpl::GetForceFeedbackCommand(const AActor* ActorThumbTouching,
const AActor* ActorIndexTouching,
const AActor* ActorMiddleTouching,
const AActor* ActorRingTouching,
const AActor* ActorPinkyTouching) const
{
USGForceFeedbackCommand* ForceFeedbackCommand = USGForceFeedbackCommand::NewForceFeedbackCommand(
Owner,
GetForceFeedbackLevel(ActorThumbTouching),
GetForceFeedbackLevel(ActorIndexTouching),
GetForceFeedbackLevel(ActorMiddleTouching),
GetForceFeedbackLevel(ActorRingTouching),
GetForceFeedbackLevel(ActorPinkyTouching)
);
return ForceFeedbackCommand;
}
void ASGPlayerController::FImplDeleter::operator()(const FImpl* P) const
{
delete P;
}
@@ -36,6 +36,7 @@
#pragma once
#include "GameFramework/PlayerController.h"
#include "Templates/UniquePtr.h"
#include "SGPlayerController.generated.h"
@@ -44,6 +45,17 @@ class SENSEGLOVE_API ASGPlayerController : public APlayerController
{
GENERATED_UCLASS_BODY()
private:
struct FImpl;
struct FImplDeleter
{
void operator()(const FImpl* P) const;
};
TUniquePtr<FImpl, FImplDeleter> Pimpl;
FImplDeleter PimplDeleter;
protected:
virtual void SetupInputComponent() override;
virtual void BeginPlay() override;
};