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 "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;
|
||||
};
|
||||
Reference in New Issue
Block a user