diff --git a/CHANGELOG.md b/CHANGELOG.md index 7a76d847..08dc8fbf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,17 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [ Unreleased ] + +### Added + +- Introduced new SGPawn events: OnActorGrabbed, OnActorReleased, OnActorBeginTouch, and OnActorEndTouch. +- Exposed OnGrabStateUpdated, OnTouchStateUpdated, OnActorGrabbed, OnActorReleased, OnActorBeginTouch, and OnActorEndTouch events to Blueprint as BlueprintImplementableEvent. + +### Fixed + +- Fix a bug where the OnTouchStateUpdated event is mistakenly triggered instead of the OnGrabStateUpdated when the right thumb fingertip grab collider overlaps with a grabbable actor. + ## [1.7.0] - 2023-09-14 ### Added diff --git a/Source/SenseGlove/Private/SenseGlove/GameFramework/SGPawn.cpp b/Source/SenseGlove/Private/SenseGlove/GameFramework/SGPawn.cpp index dc9d266a..f61b1a66 100644 --- a/Source/SenseGlove/Private/SenseGlove/GameFramework/SGPawn.cpp +++ b/Source/SenseGlove/Private/SenseGlove/GameFramework/SGPawn.cpp @@ -145,6 +145,13 @@ struct ASGPawn::FImpl void RecordHandVelocity(FSGGrabState& GrabState, const float DeltaSeconds) const; void Release(FSGGrabState& GrabState) const; + + void TriggerGrabStateUpdatedEvent(const FSGGrabState& GrabState) const; + void TriggerTouchStateUpdatedEvent(const FSGTouchState& TouchState) const; + void TriggerActorGrabbedEvent(const USGVirtualHandComponent* Hand, const AActor* Actor) const; + void TriggerActorReleasedEvent(const USGVirtualHandComponent* Hand, const AActor* Actor) const; + void TriggerBeginTouch(const USGVirtualHandComponent* Hand, const AActor* Actor) const; + void TriggerEndTouch(const USGVirtualHandComponent* Hand, const AActor* Actor) const; }; ASGPawn::ASGPawn(const FObjectInitializer& ObjectInitializer) @@ -781,7 +788,7 @@ void ASGPawn::OnLeftThumbFingertipGrabColliderOverlapBegins( if (USGGrabComponent::IsGrabbable(OtherActor)) { LeftHandGrabState.ActorThumbCanGrab = OtherActor; - GrabStateUpdatedEvent.Broadcast(LeftHandGrabState); + Pimpl->TriggerGrabStateUpdatedEvent(LeftHandGrabState); } } @@ -798,7 +805,7 @@ void ASGPawn::OnLeftThumbFingertipGrabColliderOverlapEnds( if (LeftHandGrabState.ActorThumbCanGrab == OtherActor) { LeftHandGrabState.ActorThumbCanGrab = nullptr; - GrabStateUpdatedEvent.Broadcast(LeftHandGrabState); + Pimpl->TriggerGrabStateUpdatedEvent(LeftHandGrabState); } } @@ -819,7 +826,7 @@ void ASGPawn::OnLeftIndexFingertipGrabColliderOverlapBegins( if (USGGrabComponent::IsGrabbable(OtherActor)) { LeftHandGrabState.ActorIndexCanGrab = OtherActor; - GrabStateUpdatedEvent.Broadcast(LeftHandGrabState); + Pimpl->TriggerGrabStateUpdatedEvent(LeftHandGrabState); } } @@ -836,7 +843,7 @@ void ASGPawn::OnLeftIndexFingertipGrabColliderOverlapEnds( if (LeftHandGrabState.ActorIndexCanGrab == OtherActor) { LeftHandGrabState.ActorIndexCanGrab = nullptr; - GrabStateUpdatedEvent.Broadcast(LeftHandGrabState); + Pimpl->TriggerGrabStateUpdatedEvent(LeftHandGrabState); } } @@ -857,7 +864,7 @@ void ASGPawn::OnLeftMiddleFingertipGrabColliderOverlapBegins( if (USGGrabComponent::IsGrabbable(OtherActor)) { LeftHandGrabState.ActorMiddleCanGrab = OtherActor; - GrabStateUpdatedEvent.Broadcast(LeftHandGrabState); + Pimpl->TriggerGrabStateUpdatedEvent(LeftHandGrabState); } } @@ -874,7 +881,7 @@ void ASGPawn::OnLeftMiddleFingertipGrabColliderOverlapEnds( if (LeftHandGrabState.ActorMiddleCanGrab == OtherActor) { LeftHandGrabState.ActorMiddleCanGrab = nullptr; - GrabStateUpdatedEvent.Broadcast(LeftHandGrabState); + Pimpl->TriggerGrabStateUpdatedEvent(LeftHandGrabState); } } @@ -895,7 +902,8 @@ void ASGPawn::OnLeftThumbFingertipTouchColliderOverlapBegins( if (USGTouchComponent::IsTouchable(OtherActor)) { LeftHandTouchState.ActorThumbTouching = OtherActor; - TouchStateUpdatedEvent.Broadcast(LeftHandTouchState); + Pimpl->TriggerTouchStateUpdatedEvent(LeftHandTouchState); + Pimpl->TriggerBeginTouch(LeftHandTouchState.Hand, OtherActor); } } @@ -912,7 +920,8 @@ void ASGPawn::OnLeftThumbFingertipTouchColliderOverlapEnds( if (LeftHandTouchState.ActorThumbTouching == OtherActor) { LeftHandTouchState.ActorThumbTouching = nullptr; - TouchStateUpdatedEvent.Broadcast(LeftHandTouchState); + Pimpl->TriggerTouchStateUpdatedEvent(LeftHandTouchState); + Pimpl->TriggerEndTouch(LeftHandTouchState.Hand, OtherActor); } } @@ -933,7 +942,8 @@ void ASGPawn::OnLeftIndexFingertipTouchColliderOverlapBegins( if (USGTouchComponent::IsTouchable(OtherActor)) { LeftHandTouchState.ActorIndexTouching = OtherActor; - TouchStateUpdatedEvent.Broadcast(LeftHandTouchState); + Pimpl->TriggerTouchStateUpdatedEvent(LeftHandTouchState); + Pimpl->TriggerBeginTouch(LeftHandTouchState.Hand, OtherActor); } } @@ -950,7 +960,8 @@ void ASGPawn::OnLeftIndexFingertipTouchColliderOverlapEnds( if (LeftHandTouchState.ActorIndexTouching == OtherActor) { LeftHandTouchState.ActorIndexTouching = nullptr; - TouchStateUpdatedEvent.Broadcast(LeftHandTouchState); + Pimpl->TriggerTouchStateUpdatedEvent(LeftHandTouchState); + Pimpl->TriggerEndTouch(LeftHandTouchState.Hand, OtherActor); } } @@ -971,7 +982,8 @@ void ASGPawn::OnLeftMiddleFingertipTouchColliderOverlapBegins( if (USGTouchComponent::IsTouchable(OtherActor)) { LeftHandTouchState.ActorMiddleTouching = OtherActor; - TouchStateUpdatedEvent.Broadcast(LeftHandTouchState); + Pimpl->TriggerTouchStateUpdatedEvent(LeftHandTouchState); + Pimpl->TriggerBeginTouch(LeftHandTouchState.Hand, OtherActor); } } @@ -988,7 +1000,8 @@ void ASGPawn::OnLeftMiddleFingertipTouchColliderOverlapEnds( if (LeftHandTouchState.ActorMiddleTouching == OtherActor) { LeftHandTouchState.ActorMiddleTouching = nullptr; - TouchStateUpdatedEvent.Broadcast(LeftHandTouchState); + Pimpl->TriggerTouchStateUpdatedEvent(LeftHandTouchState); + Pimpl->TriggerEndTouch(LeftHandTouchState.Hand, OtherActor); } } @@ -1009,7 +1022,8 @@ void ASGPawn::OnLeftRingFingertipTouchColliderOverlapBegins( if (USGTouchComponent::IsTouchable(OtherActor)) { LeftHandTouchState.ActorRingTouching = OtherActor; - TouchStateUpdatedEvent.Broadcast(LeftHandTouchState); + Pimpl->TriggerTouchStateUpdatedEvent(LeftHandTouchState); + Pimpl->TriggerBeginTouch(LeftHandTouchState.Hand, OtherActor); } } @@ -1026,7 +1040,8 @@ void ASGPawn::OnLeftRingFingertipTouchColliderOverlapEnds( if (LeftHandTouchState.ActorRingTouching == OtherActor) { LeftHandTouchState.ActorRingTouching = nullptr; - TouchStateUpdatedEvent.Broadcast(LeftHandTouchState); + Pimpl->TriggerTouchStateUpdatedEvent(LeftHandTouchState); + Pimpl->TriggerEndTouch(LeftHandTouchState.Hand, OtherActor); } } @@ -1047,7 +1062,8 @@ void ASGPawn::OnLeftPinkyFingertipTouchColliderOverlapBegins( if (USGTouchComponent::IsTouchable(OtherActor)) { LeftHandTouchState.ActorPinkyTouching = OtherActor; - TouchStateUpdatedEvent.Broadcast(LeftHandTouchState); + Pimpl->TriggerTouchStateUpdatedEvent(LeftHandTouchState); + Pimpl->TriggerBeginTouch(LeftHandTouchState.Hand, OtherActor); } } @@ -1064,7 +1080,8 @@ void ASGPawn::OnLeftPinkyFingertipTouchColliderOverlapEnds( if (LeftHandTouchState.ActorPinkyTouching == OtherActor) { LeftHandTouchState.ActorPinkyTouching = nullptr; - TouchStateUpdatedEvent.Broadcast(LeftHandTouchState); + Pimpl->TriggerTouchStateUpdatedEvent(LeftHandTouchState); + Pimpl->TriggerEndTouch(LeftHandTouchState.Hand, OtherActor); } } @@ -1085,7 +1102,7 @@ void ASGPawn::OnRightThumbFingertipGrabColliderOverlapBegins( if (USGGrabComponent::IsGrabbable(OtherActor)) { RightHandGrabState.ActorThumbCanGrab = OtherActor; - TouchStateUpdatedEvent.Broadcast(LeftHandTouchState); + Pimpl->TriggerGrabStateUpdatedEvent(RightHandGrabState); } } @@ -1102,7 +1119,7 @@ void ASGPawn::OnRightThumbFingertipGrabColliderOverlapEnds( if (RightHandGrabState.ActorThumbCanGrab == OtherActor) { RightHandGrabState.ActorThumbCanGrab = nullptr; - GrabStateUpdatedEvent.Broadcast(RightHandGrabState); + Pimpl->TriggerGrabStateUpdatedEvent(RightHandGrabState); } } @@ -1123,7 +1140,7 @@ void ASGPawn::OnRightIndexFingertipGrabColliderOverlapBegins( if (USGGrabComponent::IsGrabbable(OtherActor)) { RightHandGrabState.ActorIndexCanGrab = OtherActor; - GrabStateUpdatedEvent.Broadcast(RightHandGrabState); + Pimpl->TriggerGrabStateUpdatedEvent(RightHandGrabState); } } @@ -1140,7 +1157,7 @@ void ASGPawn::OnRightIndexFingertipGrabColliderOverlapEnds( if (RightHandGrabState.ActorThumbCanGrab == OtherActor) { RightHandGrabState.ActorIndexCanGrab = nullptr; - GrabStateUpdatedEvent.Broadcast(RightHandGrabState); + Pimpl->TriggerGrabStateUpdatedEvent(RightHandGrabState); } } @@ -1161,7 +1178,7 @@ void ASGPawn::OnRightMiddleFingertipGrabColliderOverlapBegins( if (USGGrabComponent::IsGrabbable(OtherActor)) { RightHandGrabState.ActorMiddleCanGrab = OtherActor; - GrabStateUpdatedEvent.Broadcast(RightHandGrabState); + Pimpl->TriggerGrabStateUpdatedEvent(RightHandGrabState); } } @@ -1178,7 +1195,7 @@ void ASGPawn::OnRightMiddleFingertipGrabColliderOverlapEnds( if (RightHandGrabState.ActorMiddleCanGrab == OtherActor) { RightHandGrabState.ActorMiddleCanGrab = nullptr; - GrabStateUpdatedEvent.Broadcast(RightHandGrabState); + Pimpl->TriggerGrabStateUpdatedEvent(RightHandGrabState); } } @@ -1199,7 +1216,8 @@ void ASGPawn::OnRightThumbFingertipTouchColliderOverlapBegins( if (USGTouchComponent::IsTouchable(OtherActor)) { RightHandTouchState.ActorThumbTouching = OtherActor; - TouchStateUpdatedEvent.Broadcast(RightHandTouchState); + Pimpl->TriggerTouchStateUpdatedEvent(RightHandTouchState); + Pimpl->TriggerBeginTouch(RightHandTouchState.Hand, OtherActor); } } @@ -1216,7 +1234,8 @@ void ASGPawn::OnRightThumbFingertipTouchColliderOverlapEnds( if (RightHandTouchState.ActorThumbTouching == OtherActor) { RightHandTouchState.ActorThumbTouching = nullptr; - TouchStateUpdatedEvent.Broadcast(RightHandTouchState); + Pimpl->TriggerTouchStateUpdatedEvent(RightHandTouchState); + Pimpl->TriggerEndTouch(RightHandTouchState.Hand, OtherActor); } } @@ -1237,7 +1256,8 @@ void ASGPawn::OnRightIndexFingertipTouchColliderOverlapBegins( if (USGTouchComponent::IsTouchable(OtherActor)) { RightHandTouchState.ActorIndexTouching = OtherActor; - TouchStateUpdatedEvent.Broadcast(RightHandTouchState); + Pimpl->TriggerTouchStateUpdatedEvent(RightHandTouchState); + Pimpl->TriggerBeginTouch(RightHandTouchState.Hand, OtherActor); } } @@ -1254,7 +1274,8 @@ void ASGPawn::OnRightIndexFingertipTouchColliderOverlapEnds( if (RightHandTouchState.ActorIndexTouching == OtherActor) { RightHandTouchState.ActorIndexTouching = nullptr; - TouchStateUpdatedEvent.Broadcast(RightHandTouchState); + Pimpl->TriggerTouchStateUpdatedEvent(RightHandTouchState); + Pimpl->TriggerEndTouch(RightHandTouchState.Hand, OtherActor); } } @@ -1275,7 +1296,8 @@ void ASGPawn::OnRightMiddleFingertipTouchColliderOverlapBegins( if (USGTouchComponent::IsTouchable(OtherActor)) { RightHandTouchState.ActorMiddleTouching = OtherActor; - TouchStateUpdatedEvent.Broadcast(RightHandTouchState); + Pimpl->TriggerTouchStateUpdatedEvent(RightHandTouchState); + Pimpl->TriggerBeginTouch(RightHandTouchState.Hand, OtherActor); } } @@ -1292,7 +1314,8 @@ void ASGPawn::OnRightMiddleFingertipTouchColliderOverlapEnds( if (RightHandTouchState.ActorMiddleTouching == OtherActor) { RightHandTouchState.ActorMiddleTouching = nullptr; - TouchStateUpdatedEvent.Broadcast(RightHandTouchState); + Pimpl->TriggerTouchStateUpdatedEvent(RightHandTouchState); + Pimpl->TriggerEndTouch(RightHandTouchState.Hand, OtherActor); } } @@ -1313,7 +1336,8 @@ void ASGPawn::OnRightRingFingertipTouchColliderOverlapBegins( if (USGTouchComponent::IsTouchable(OtherActor)) { RightHandTouchState.ActorRingTouching = OtherActor; - TouchStateUpdatedEvent.Broadcast(RightHandTouchState); + Pimpl->TriggerTouchStateUpdatedEvent(RightHandTouchState); + Pimpl->TriggerBeginTouch(RightHandTouchState.Hand, OtherActor); } } @@ -1330,7 +1354,8 @@ void ASGPawn::OnRightRingFingertipTouchColliderOverlapEnds( if (RightHandTouchState.ActorRingTouching == OtherActor) { RightHandTouchState.ActorRingTouching = nullptr; - TouchStateUpdatedEvent.Broadcast(RightHandTouchState); + Pimpl->TriggerTouchStateUpdatedEvent(RightHandTouchState); + Pimpl->TriggerEndTouch(RightHandTouchState.Hand, OtherActor); } } @@ -1351,7 +1376,8 @@ void ASGPawn::OnRightPinkyFingertipTouchColliderOverlapBegins( if (USGTouchComponent::IsTouchable(OtherActor)) { RightHandTouchState.ActorPinkyTouching = OtherActor; - TouchStateUpdatedEvent.Broadcast(RightHandTouchState); + Pimpl->TriggerTouchStateUpdatedEvent(RightHandTouchState); + Pimpl->TriggerBeginTouch(RightHandTouchState.Hand, OtherActor); } } @@ -1368,7 +1394,8 @@ void ASGPawn::OnRightPinkyFingertipTouchColliderOverlapEnds( if (RightHandTouchState.ActorPinkyTouching == OtherActor) { RightHandTouchState.ActorPinkyTouching = nullptr; - TouchStateUpdatedEvent.Broadcast(RightHandTouchState); + Pimpl->TriggerTouchStateUpdatedEvent(RightHandTouchState); + Pimpl->TriggerEndTouch(RightHandTouchState.Hand, OtherActor); } } @@ -1471,6 +1498,8 @@ void ASGPawn::Grab(USGVirtualHandComponent* Hand, AActor* Actor) Pimpl->SetLeftHandGrabbedActor(Actor); } #endif /* ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 2 */ + + Pimpl->TriggerActorGrabbedEvent(Hand, Actor); } void ASGPawn::ReleaseLeft() @@ -1924,6 +1953,44 @@ void ASGPawn::FImpl::Release(FSGGrabState& GrabState) const ApplyHandVelocityToGrabbedActor(GrabState); SetGrabbedActor(GrabState, nullptr); + + TriggerActorReleasedEvent(GrabState.Hand, GrabState.GrabbedActor); +} + +void ASGPawn::FImpl::TriggerGrabStateUpdatedEvent(const FSGGrabState& GrabState) const +{ + Owner->GrabStateUpdatedEvent.Broadcast(GrabState); + Owner->OnGrabStateUpdated(GrabState); +} + +void ASGPawn::FImpl::TriggerTouchStateUpdatedEvent(const FSGTouchState& TouchState) const +{ + Owner->TouchStateUpdatedEvent.Broadcast(TouchState); + Owner->OnTouchStateUpdated(TouchState); +} + +void ASGPawn::FImpl::TriggerActorGrabbedEvent(const USGVirtualHandComponent* Hand, const AActor* Actor) const +{ + Owner->ActorGrabbedEvent.Broadcast(Hand, Actor); + Owner->OnActorGrabbed(Hand, Actor); +} + +void ASGPawn::FImpl::TriggerActorReleasedEvent(const USGVirtualHandComponent* Hand, const AActor* Actor) const +{ + Owner->ActorReleasedEvent.Broadcast(Hand, Actor); + Owner->OnActorReleased(Hand, Actor); +} + +void ASGPawn::FImpl::TriggerBeginTouch(const USGVirtualHandComponent* Hand, const AActor* Actor) const +{ + Owner->ActorBeginTouchEvent.Broadcast(Hand, Actor); + Owner->OnActorBeginTouch(Hand, Actor); +} + +void ASGPawn::FImpl::TriggerEndTouch(const USGVirtualHandComponent* Hand, const AActor* Actor) const +{ + Owner->ActorEndTouchEvent.Broadcast(Hand, Actor); + Owner->OnActorEndTouch(Hand, Actor); } ASGPawn::FImpl::~FImpl() = default; diff --git a/Source/SenseGlove/Public/SenseGlove/GameFramework/SGPawn.h b/Source/SenseGlove/Public/SenseGlove/GameFramework/SGPawn.h index 0efe3653..22c50acb 100644 --- a/Source/SenseGlove/Public/SenseGlove/GameFramework/SGPawn.h +++ b/Source/SenseGlove/Public/SenseGlove/GameFramework/SGPawn.h @@ -58,23 +58,55 @@ class SENSEGLOVE_API ASGPawn : public APawn GENERATED_UCLASS_BODY() public: - DECLARE_EVENT_OneParam(ASGVirtualHandActor, FGrabStateUpdatedEvent, const FSGGrabState& GrabState); + DECLARE_EVENT_OneParam(ASGPawn, FGrabStateUpdatedEvent, const FSGGrabState& GrabState); FGrabStateUpdatedEvent& OnGrabStateUpdated() { return GrabStateUpdatedEvent; }; - DECLARE_EVENT_OneParam(ASGVirtualHandActor, FTouchStateUpdatedEvent, const FSGTouchState& TouchState) + DECLARE_EVENT_OneParam(ASGPawn, FTouchStateUpdatedEvent, const FSGTouchState& TouchState) FTouchStateUpdatedEvent& OnTouchStateUpdated() { return TouchStateUpdatedEvent; }; + DECLARE_EVENT_TwoParams(ASGPawn, FActorGrabbedEvent, const USGVirtualHandComponent* Hand, const AActor* Actor); + + FActorGrabbedEvent& OnGrabbed() + { + return ActorGrabbedEvent; + }; + + DECLARE_EVENT_TwoParams(ASGPawn, FActorReleasedEvent, const USGVirtualHandComponent* Hand, const AActor* Actor); + + FActorReleasedEvent& OnReleased() + { + return ActorReleasedEvent; + }; + + DECLARE_EVENT_TwoParams(ASGPawn, FActorBeginTouchEvent, const USGVirtualHandComponent* Hand, const AActor* Actor); + + FActorBeginTouchEvent& OnActorBeginTouch() + { + return ActorBeginTouchEvent; + }; + + DECLARE_EVENT_TwoParams(ASGPawn, FActorEndTouchEvent, const USGVirtualHandComponent* Hand, const AActor* Actor); + + FActorEndTouchEvent& OnActorEndTouch() + { + return ActorEndTouchEvent; + }; + private: FGrabStateUpdatedEvent GrabStateUpdatedEvent; FTouchStateUpdatedEvent TouchStateUpdatedEvent; + FActorGrabbedEvent ActorGrabbedEvent; + FActorReleasedEvent ActorReleasedEvent; + FActorBeginTouchEvent ActorBeginTouchEvent; + FActorEndTouchEvent ActorEndTouchEvent; private: struct FImpl; @@ -182,6 +214,25 @@ private: UPROPERTY(Transient) TArray RightHandOverlappedActors; +protected: + UFUNCTION(BlueprintImplementableEvent, Category="SenseGlove | Game Framework | Pawn") + void OnGrabStateUpdated(const FSGGrabState& GrabState); + + UFUNCTION(BlueprintImplementableEvent, Category="SenseGlove | Game Framework | Pawn") + void OnTouchStateUpdated(const FSGTouchState& TouchState); + + UFUNCTION(BlueprintImplementableEvent, Category="SenseGlove | Game Framework | Pawn") + void OnActorGrabbed(const USGVirtualHandComponent* Hand, const AActor* Actor); + + UFUNCTION(BlueprintImplementableEvent, Category="SenseGlove | Game Framework | Pawn") + void OnActorReleased(const USGVirtualHandComponent* Hand, const AActor* Actor); + + UFUNCTION(BlueprintImplementableEvent, Category="SenseGlove | Game Framework | Pawn") + void OnActorBeginTouch(const USGVirtualHandComponent* Hand, const AActor* Actor); + + UFUNCTION(BlueprintImplementableEvent, Category="SenseGlove | Game Framework | Pawn") + void OnActorEndTouch(const USGVirtualHandComponent* Hand, const AActor* Actor); + public: FORCEINLINE UCameraComponent* GetCamera() const {