diff --git a/Source/DisplayClusterExtensions/Private/Pawn/BasicVRInteractionComponent.cpp b/Source/DisplayClusterExtensions/Private/Pawn/BasicVRInteractionComponent.cpp index c0a06d49cb89fb87288b1246293ce0335f26764d..0f3441165724e615f4fc7f2ca47416c29cf93c1b 100644 --- a/Source/DisplayClusterExtensions/Private/Pawn/BasicVRInteractionComponent.cpp +++ b/Source/DisplayClusterExtensions/Private/Pawn/BasicVRInteractionComponent.cpp @@ -104,15 +104,44 @@ void UBasicVRInteractionComponent::TickComponent(float DeltaTime, ELevelTick Tic const FTwoVectors StartEnd = GetHandRay(MaxClickDistance); TOptional<FHitResult> Hit = RaytraceForFirstHit(StartEnd); + if (!Hit.IsSet()) + { + + // Execute leave event on the actor that lost the focus if there was one + if (LastActorHit && LastActorHit->Implements<UTargetable>()) + { + ITargetable::Execute_OnTargetedLeave(LastActorHit); + } + + LastActorHit = nullptr; return; + } + AActor* HitActor = Hit->GetActor(); + // Execute Leave and enter events when the focused actor changed + if (HitActor != LastActorHit) + { + //We can always execute the enter event as we are sure that a hit occured + if (HitActor->Implements<UTargetable>()) + { + ITargetable::Execute_OnTargetedEnter(HitActor); + } + + //Only execute the Leave Event if there was an actor that was focused previously + if (LastActorHit != nullptr && LastActorHit->Implements<UTargetable>()) + { + ITargetable::Execute_OnTargetedLeave(LastActorHit); + } + } + // for now uses the same distance as clicking if (HitActor->Implements<UTargetable>() && Hit->Distance < MaxClickDistance) { ITargetable::Execute_OnTargeted(HitActor, Hit->Location); } + LastActorHit = HitActor; // Store the actor that was hit to have access to it in the next frame as well } void UBasicVRInteractionComponent::Initialize(USceneComponent* RayEmitter, float InMaxGrabDistance, float InMaxClickDistance) diff --git a/Source/DisplayClusterExtensions/Public/Interaction/Targetable.h b/Source/DisplayClusterExtensions/Public/Interaction/Targetable.h index a11da8bd223ecfdc4f66863eabc70d71ee5f15e8..3dd1e6a78ec0deb75edfe75ad3a65a82c00eaa35 100644 --- a/Source/DisplayClusterExtensions/Public/Interaction/Targetable.h +++ b/Source/DisplayClusterExtensions/Public/Interaction/Targetable.h @@ -22,4 +22,12 @@ public: // function that will be called when clickable actor got clicked, and passed the world pos of the click UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = Gameplay) void OnTargeted(FVector WorldPositionOfTarget); + + //function that will be called when a targetable actor gets focused + UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = Gameplay) + void OnTargetedEnter(); + + //function that will be called when a targetable actor loses focused + UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = Gameplay) + void OnTargetedLeave(); }; diff --git a/Source/DisplayClusterExtensions/Public/Pawn/BasicVRInteractionComponent.h b/Source/DisplayClusterExtensions/Public/Pawn/BasicVRInteractionComponent.h index 6e86c208e971ad141a34c489bc1d6d3aca123d5c..92bb238716cc9f86366c4a9fd8bf90c76b9a556e 100644 --- a/Source/DisplayClusterExtensions/Public/Pawn/BasicVRInteractionComponent.h +++ b/Source/DisplayClusterExtensions/Public/Pawn/BasicVRInteractionComponent.h @@ -40,7 +40,8 @@ private: UPROPERTY() UPrimitiveComponent* ComponentSimulatingPhysics = nullptr; UPROPERTY() UGrabbingBehaviorComponent* Behavior = nullptr; UPROPERTY() USceneComponent* InteractionRayEmitter = nullptr; - + /* Stores the reference of the Actor that was hit in the last frame*/ + UPROPERTY() AActor* LastActorHit = nullptr; void HandlePhysicsAndAttachActor(AActor* HitActor); FTwoVectors GetHandRay(float Length) const; TOptional<FHitResult> RaytraceForFirstHit(const FTwoVectors& Ray) const;