// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "Components/WidgetInteractionComponent.h" #include "BasicVRInteractionComponent.generated.h" DECLARE_LOG_CATEGORY_EXTERN(LogVRInteractionComponent, Log, All); class UGrabbingBehaviorComponent; UENUM() enum EInteractionRayVisibility { Visible UMETA(DisplayName = "Interaction ray visible"), VisibleOnHoverOnly UMETA(DisplayName = "Interaction ray only visible when hovering over Clickable or Targetable objects, or interactable widgets"), Invisible UMETA(DisplayName = "Interaction ray invisible") }; UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) ) class DISPLAYCLUSTEREXTENSIONS_API UBasicVRInteractionComponent : public UWidgetInteractionComponent { GENERATED_BODY() public: // Sets default values for this component's properties UBasicVRInteractionComponent(); void BeginPlay() override; UFUNCTION(BlueprintCallable) void BeginInteraction(); UFUNCTION(BlueprintCallable) void EndInteraction(); // Called every frame virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override; UPROPERTY(BlueprintReadWrite) float MaxGrabDistance = 50; UPROPERTY(BlueprintReadWrite) float MaxClickDistance = 500; // Enable this if you want to interact with Targetable classes or use EInteractionRayVisibility::VisibleOnHoverOnly UPROPERTY(EditAnywhere) bool bCanRaytraceEveryTick = false; UPROPERTY(EditAnywhere) TEnumAsByte<EInteractionRayVisibility> InteractionRayVisibility = EInteractionRayVisibility::Invisible; UFUNCTION(BlueprintCallable) void Initialize(USceneComponent* RayEmitter, float InMaxGrabDistance = 50, float InMaxClickDistance = 500); UFUNCTION(BlueprintCallable, BlueprintPure) AActor* GetGrabbedActor() const { return GrabbedActor;} UFUNCTION(BlueprintCallable, BlueprintPure) USceneComponent* GetInteractionRayEmitter() const { return InteractionRayEmitter; } UFUNCTION(BlueprintCallable) void SetInteractionRayVisibility(EInteractionRayVisibility NewVisibility); private: /* Holding a reference to the actor that is currently being grabbed */ UPROPERTY() AActor* GrabbedActor; /* Holds a reference to the grabbed actors physics simulating component if there was one*/ UPROPERTY() UPrimitiveComponent* ComponentSimulatingPhysics = nullptr; UPROPERTY() UGrabbingBehaviorComponent* Behavior = nullptr; UPROPERTY() USceneComponent* InteractionRayEmitter = nullptr; UPROPERTY() UStaticMeshComponent* InteractionRay = 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; }; // Free utility functions /* Returns the UPrimitiveComponent simulating physics that is highest in the hierarchy */ UPrimitiveComponent* GetFirstComponentSimulatingPhysics(const AActor* TargetActor); /* Recursive Function If parent component simulates physics returns GetHighestParentSimulatingPhysics(Parent) else returns Comp itself */ UPrimitiveComponent* GetHighestParentSimulatingPhysics(UPrimitiveComponent* Comp);