apply the hand's velocity to the grabbed actor after release

This commit is contained in:
Mamadou Babaei
2023-08-14 17:25:48 +02:00
parent d4e92546e3
commit bb63748644
2 changed files with 95 additions and 54 deletions
@@ -83,6 +83,14 @@ struct ASGPawn::FImpl
void DisableActorPhysics(const AActor* Actor) const;
void EnableActorPhysics(const AActor* Actor) const;
void ApplyHandVelocityToGrabbedActor(const FSGGrabState& GrabState) const;
void SetGrabbedActor(FSGGrabState& GrabState, AActor* Actor) const;
void SetLeftHandGrabbedActor(AActor* Actor) const;
void SetRightHandGrabbedActor(AActor* Actor) const;
void Release(FSGGrabState& GrabState) const;
};
ASGPawn::ASGPawn(const FObjectInitializer& ObjectInitializer)
@@ -1147,11 +1155,11 @@ void ASGPawn::Grab(USGVirtualHandComponent* Hand, AActor* Actor)
{
if (Hand->IsRight())
{
RightHandGrabState.GrabbedActor = Actor;
Pimpl->SetRightHandGrabbedActor(Actor);
}
else
{
LeftHandGrabState.GrabbedActor = Actor;
Pimpl->SetLeftHandGrabbedActor(Actor);
}
}
else
@@ -1169,69 +1177,23 @@ void ASGPawn::Grab(USGVirtualHandComponent* Hand, AActor* Actor)
Actor->AttachToComponent(Hand, MoveTemp(AttachmentRules), SocketName);
if (Hand->IsRight())
{
RightHandGrabState.GrabbedActor = Actor;
Pimpl->SetRightHandGrabbedActor(Actor);
}
else
{
LeftHandGrabState.GrabbedActor = Actor;
Pimpl->SetLeftHandGrabbedActor(Actor);
}
#endif /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 2 */
}
void ASGPawn::ReleaseLeft()
{
if (!IsValid(LeftHandGrabState.GrabbedActor))
{
return;
}
const USGGrabComponent* GrabComponent{USGGrabComponent::GetGrabComponent(LeftHandGrabState.GrabbedActor)};
if (!IsValid(GrabComponent))
{
return;
}
LeftHandGrabState.GrabbedActor->DetachFromActor(
FDetachmentTransformRules(GrabComponent->GetDetachmentLocationRule(),
GrabComponent->GetDetachmentRotationRule(),
GrabComponent->GetDetachmentScaleRule(),
GrabComponent->GetDetachmentInCallModify())
);
if (GrabComponent->GetAffectPhysicsState())
{
Pimpl->EnableActorPhysics(LeftHandGrabState.GrabbedActor);
}
LeftHandGrabState.GrabbedActor = nullptr;
Pimpl->Release(LeftHandGrabState);
}
void ASGPawn::ReleaseRight()
{
if (!IsValid(RightHandGrabState.GrabbedActor))
{
return;
}
const USGGrabComponent* GrabComponent{USGGrabComponent::GetGrabComponent(RightHandGrabState.GrabbedActor)};
if (!IsValid(GrabComponent))
{
return;
}
RightHandGrabState.GrabbedActor->DetachFromActor(
FDetachmentTransformRules(GrabComponent->GetDetachmentLocationRule(),
GrabComponent->GetDetachmentRotationRule(),
GrabComponent->GetDetachmentScaleRule(),
GrabComponent->GetDetachmentInCallModify())
);
if (GrabComponent->GetAffectPhysicsState())
{
Pimpl->EnableActorPhysics(RightHandGrabState.GrabbedActor);
}
RightHandGrabState.GrabbedActor = nullptr;
Pimpl->Release(RightHandGrabState);
}
ASGPawn::FImpl::FImpl(ASGPawn* InOwner)
@@ -1429,7 +1391,6 @@ void ASGPawn::FImpl::UnbindFingerTouchOverlapEvents()
void ASGPawn::FImpl::DisableActorPhysics(const AActor* Actor) const
{
UPrimitiveComponent* ActorRootComponent{Cast<UPrimitiveComponent>(Actor->GetRootComponent())};
if (!ensureAlwaysMsgf(IsValid(ActorRootComponent), TEXT("RootComponent is not a valid UPrimativeComponent!")))
{
return;
@@ -1437,6 +1398,7 @@ void ASGPawn::FImpl::DisableActorPhysics(const AActor* Actor) const
ActorRootComponent->SetEnableGravity(false);
ActorRootComponent->SetSimulatePhysics(false);
ActorRootComponent->PutRigidBodyToSleep();
}
void ASGPawn::FImpl::EnableActorPhysics(const AActor* Actor) const
@@ -1447,7 +1409,6 @@ void ASGPawn::FImpl::EnableActorPhysics(const AActor* Actor) const
}
UPrimitiveComponent* ActorRootComponent{Cast<UPrimitiveComponent>(Actor->GetRootComponent())};
if (!ensureAlwaysMsgf(IsValid(ActorRootComponent), TEXT("RootComponent is not a valid UPrimativeComponent!")))
{
return;
@@ -1455,6 +1416,80 @@ void ASGPawn::FImpl::EnableActorPhysics(const AActor* Actor) const
ActorRootComponent->SetEnableGravity(true);
ActorRootComponent->SetSimulatePhysics(true);
ActorRootComponent->WakeRigidBody();
}
void ASGPawn::FImpl::ApplyHandVelocityToGrabbedActor(const FSGGrabState& GrabState) const
{
if (!IsValid(GrabState.Hand))
{
return;
}
if (!IsValid(GrabState.GrabbedActor))
{
return;
}
UPrimitiveComponent* ActorRootComponent{Cast<UPrimitiveComponent>(GrabState.GrabbedActor->GetRootComponent())};
if (!ensureAlwaysMsgf(IsValid(ActorRootComponent), TEXT("RootComponent is not a valid UPrimativeComponent!")))
{
return;
}
/// NOTE: this produces almost the same values
// FVector ActorVelocity{
// (GrabState.GrabbedActor->GetActorLocation() - GrabState.PreviousLocation) / DeltaSeconds
// };
FVector ActorVelocity{GrabState.GrabbedActor->GetVelocity()};
ActorRootComponent->SetPhysicsLinearVelocity(ActorVelocity);
ActorRootComponent->AddImpulse(MoveTemp(ActorVelocity), NAME_None, true);
}
void ASGPawn::FImpl::SetGrabbedActor(FSGGrabState& GrabState, AActor* Actor) const
{
GrabState.GrabbedActor = Actor;
}
void ASGPawn::FImpl::SetLeftHandGrabbedActor(AActor* Actor) const
{
SetGrabbedActor(Owner->LeftHandGrabState, Actor);
}
void ASGPawn::FImpl::SetRightHandGrabbedActor(AActor* Actor) const
{
SetGrabbedActor(Owner->RightHandGrabState, Actor);
}
void ASGPawn::FImpl::Release(FSGGrabState& GrabState) const
{
if (!IsValid(GrabState.GrabbedActor))
{
return;
}
const USGGrabComponent* GrabComponent{USGGrabComponent::GetGrabComponent(GrabState.GrabbedActor)};
if (!IsValid(GrabComponent))
{
return;
}
GrabState.GrabbedActor->DetachFromActor(
FDetachmentTransformRules(GrabComponent->GetDetachmentLocationRule(),
GrabComponent->GetDetachmentRotationRule(),
GrabComponent->GetDetachmentScaleRule(),
GrabComponent->GetDetachmentInCallModify())
);
if (GrabComponent->GetAffectPhysicsState())
{
EnableActorPhysics(GrabState.GrabbedActor);
}
ApplyHandVelocityToGrabbedActor(GrabState);
SetGrabbedActor(GrabState, nullptr);
}
ASGPawn::FImpl::~FImpl() = default;