add the initial implementation for the touch functionality and its feedbacks
This commit is contained in:
@@ -35,12 +35,263 @@
|
|||||||
|
|
||||||
#include "SenseGlove/GameFramework/SGPlayerController.h"
|
#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)
|
ASGPlayerController::ASGPlayerController(const FObjectInitializer& ObjectInitializer)
|
||||||
: Super(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
|
#pragma once
|
||||||
|
|
||||||
#include "GameFramework/PlayerController.h"
|
#include "GameFramework/PlayerController.h"
|
||||||
|
#include "Templates/UniquePtr.h"
|
||||||
|
|
||||||
#include "SGPlayerController.generated.h"
|
#include "SGPlayerController.generated.h"
|
||||||
|
|
||||||
@@ -44,6 +45,17 @@ class SENSEGLOVE_API ASGPlayerController : public APlayerController
|
|||||||
{
|
{
|
||||||
GENERATED_UCLASS_BODY()
|
GENERATED_UCLASS_BODY()
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct FImpl;
|
||||||
|
|
||||||
|
struct FImplDeleter
|
||||||
|
{
|
||||||
|
void operator()(const FImpl* P) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
TUniquePtr<FImpl, FImplDeleter> Pimpl;
|
||||||
|
FImplDeleter PimplDeleter;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void SetupInputComponent() override;
|
virtual void BeginPlay() override;
|
||||||
};
|
};
|
||||||
Reference in New Issue
Block a user