Skip to content
Snippets Groups Projects
Commit 084266e5 authored by David Gilbert's avatar David Gilbert :bug:
Browse files

Merge branch 'refactor/interaction_replication' into 'dev/5.4'

Interaction refactoring and replication

See merge request !91
parents f01b1ba9 60bd5087
No related branches found
No related tags found
2 merge requests!107UE5.4-2024.1-rc1,!91Interaction refactoring and replication
Showing
with 577 additions and 237 deletions
......@@ -24,3 +24,9 @@
+PropertyRedirects = (OldName="/Script/RWTHVRToolkit.RWTHVRWidgetInteractionComponent.WidgetClickInputAction",NewName="/Script/RWTHVRToolkit.RWTHVRWidgetInteractionComponent.WidgetLeftClickInputAction")
+FunctionRedirects = (OldName="/Script/RWTHVRToolkit.RWTHVRWidgetInteractionComponent.OnBeginClick",NewName="/Script/RWTHVRToolkit.RWTHVRWidgetInteractionComponent.OnBeginLeftClick")
+FunctionRedirects = (OldName="/Script/RWTHVRToolkit.RWTHVRWidgetInteractionComponent.OnEndClick",NewName="/Script/RWTHVRToolkit.RWTHVRWidgetInteractionComponent.OnEndLeftClick")
+FunctionRedirects=(OldName="/Script/RWTHVRToolkit.UBaseInteractionComponent.OnBeginInteraction",NewName="/Script/RWTHVRToolkit.UBaseInteractionComponent.OnBeginInteractionInputAction")
+FunctionRedirects=(OldName="/Script/RWTHVRToolkit.UBaseInteractionComponent.OnEndInteraction",NewName="/Script/RWTHVRToolkit.UBaseInteractionComponent.OnEndInteractionInputAction")
+FunctionRedirects=(OldName="/Script/RWTHVRToolkit.UBaseInteractionComponent.MulticastHoverBehaviourStartRpc",NewName="/Script/RWTHVRToolkit.UBaseInteractionComponent.MulticastHoverBehaviourReplicationStartRpc")
+FunctionRedirects=(OldName="/Script/RWTHVRToolkit.UBaseInteractionComponent.MulticastActionBehaviourStartRpc",NewName="/Script/RWTHVRToolkit.UBaseInteractionComponent.MulticastActionBehaviourReplicationStartRpc")
+FunctionRedirects=(OldName="/Script/RWTHVRToolkit.ActionBehaviour.OnActionStart",NewName="/Script/RWTHVRToolkit.ActionBehaviour.OnActionEvent")
+PropertyRedirects=(OldName="/Script/RWTHVRToolkit.ActionBehaviour.OnActionBeginEvent",NewName="/Script/RWTHVRToolkit.ActionBehaviour.OnActionEventEvent")
\ No newline at end of file
No preview for this file type
......@@ -6,12 +6,7 @@
// We disable ticking here, as we are mainly interested in the events
UActionBehaviour::UActionBehaviour() { PrimaryComponentTick.bCanEverTick = false; }
void UActionBehaviour::OnActionStart(USceneComponent* TriggeredComponent, const UInputAction* InputAction,
const FInputActionValue& Value)
{
}
void UActionBehaviour::OnActionEnd(USceneComponent* TriggeredComponent, const UInputAction* InputAction,
void UActionBehaviour::OnActionEvent(USceneComponent* TriggerComponent, const EInteractionEventType EventType,
const FInputActionValue& Value)
{
}
......@@ -20,13 +15,5 @@ void UActionBehaviour::BeginPlay()
{
Super::BeginPlay();
OnActionBeginEvent.AddDynamic(this, &UActionBehaviour::OnActionStart);
OnActionEndEvent.AddDynamic(this, &UActionBehaviour::OnActionEnd);
}
// Called every frame
void UActionBehaviour::TickComponent(float DeltaTime, ELevelTick TickType,
FActorComponentTickFunction* ThisTickFunction)
{
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
OnActionEventEvent.AddDynamic(this, &UActionBehaviour::OnActionEvent);
}
// Fill out your copyright notice in the Description page of Project Settings.
#include "Interaction/Interactables/BaseBehaviour.h"
......@@ -3,10 +3,26 @@
#include "Interaction/Interactables/GrabBehavior.h"
#include "Interaction/Interactables/InteractableComponent.h"
#include "Interaction/Interactables/InteractionEventType.h"
#include "Logging/StructuredLog.h"
#include "Pawn/Navigation/CollisionHandlingMovement.h"
#include "Serialization/JsonTypes.h"
#include "Utility/RWTHVRUtilities.h"
UGrabBehavior::UGrabBehavior()
{
SetIsReplicatedByDefault(true);
bExecuteOnServer = true;
bExecuteOnAllClients = false;
}
void UGrabBehavior::BeginPlay()
{
Super::BeginPlay();
OnActionReplicationStartedOriginatorEvent.AddDynamic(this, &UGrabBehavior::ReplicationOriginaterClientCallback);
}
UPrimitiveComponent* UGrabBehavior::GetFirstComponentSimulatingPhysics(const AActor* TargetActor)
{
TArray<UPrimitiveComponent*> PrimitiveComponents;
......@@ -33,16 +49,79 @@ UPrimitiveComponent* UGrabBehavior::GetHighestParentSimulatingPhysics(UPrimitive
return Comp;
}
void UGrabBehavior::ReplicationOriginaterClientCallback(USceneComponent* TriggerComponent,
const EInteractionEventType EventType,
const FInputActionValue& Value)
{
const USceneComponent* CurrentAttachParent = Cast<USceneComponent>(TriggerComponent->GetAttachParent());
HandleCollisionHandlingMovement(CurrentAttachParent, EventType);
}
void UGrabBehavior::OnActionStart(USceneComponent* TriggeredComponent, const UInputAction* InputAction,
void UGrabBehavior::HandleCollisionHandlingMovement(const USceneComponent* CurrentAttachParent,
const EInteractionEventType EventType)
{
auto CHM = CurrentAttachParent->GetOwner()->GetComponentByClass<UCollisionHandlingMovement>();
if (!CHM)
return;
if (EventType == EInteractionEventType::InteractionStart)
{
// Add to ignore list for collision handling movement, if it exists
if (bIgnoreGrabbedActorInCollisionMovement)
{
bWasAddedToIgnore = CHM->AddActorToIgnore(GetOwner());
}
}
else
{
// If our attach parent has a collision handling component, remove
if (bWasAddedToIgnore)
{
CHM->RemoveActorFromIgnore(GetOwner());
}
}
}
void UGrabBehavior::OnActionEvent(USceneComponent* TriggerComponent, const EInteractionEventType EventType,
const FInputActionValue& Value)
{
if (EventType == EInteractionEventType::InteractionStart)
{
StartGrab(TriggerComponent);
}
else
{
EndGrab(TriggerComponent);
}
}
bool UGrabBehavior::TryRelease()
{
if (!bObjectGrabbed)
{
UE_LOGFMT(Toolkit, Display, "UGrabBehavior::TryRelease: bObjectGrabbed was false!");
return false;
}
if (MyPhysicsComponent)
{
MyPhysicsComponent->DetachFromComponent(FDetachmentTransformRules::KeepWorldTransform);
MyPhysicsComponent->SetSimulatePhysics(bWasSimulatingPhysics);
}
else
{
GetOwner()->GetRootComponent()->DetachFromComponent(FDetachmentTransformRules::KeepWorldTransform);
}
bObjectGrabbed = false;
return true;
}
void UGrabBehavior::StartGrab(USceneComponent* TriggerComponent)
{
if (bObjectGrabbed)
{
return;
}
USceneComponent* CurrentAttachParent = Cast<USceneComponent>(TriggeredComponent->GetAttachParent());
USceneComponent* CurrentAttachParent = Cast<USceneComponent>(TriggerComponent->GetAttachParent());
const FAttachmentTransformRules Rules = FAttachmentTransformRules(EAttachmentRule::KeepWorld, false);
if (MyPhysicsComponent = GetFirstComponentSimulatingPhysics(GetOwner()); MyPhysicsComponent != nullptr)
......@@ -72,18 +151,19 @@ void UGrabBehavior::OnActionStart(USceneComponent* TriggeredComponent, const UIn
GetOwner()->GetComponents<UInteractableComponent>(Interactables, false);
for (UInteractableComponent* Interactable : Interactables)
{
Interactable->RestrictInteractionToComponent(TriggeredComponent);
Interactable->RestrictInteractionToComponent(TriggerComponent);
}
}
OnGrabStartEvent.Broadcast(CurrentAttachParent, MyPhysicsComponent);
// Add to ignore list for collision handling movement, if it exists
HandleCollisionHandlingMovement(CurrentAttachParent, InteractionStart);
}
void UGrabBehavior::OnActionEnd(USceneComponent* TriggeredComponent, const UInputAction* InputAction,
const FInputActionValue& Value)
void UGrabBehavior::EndGrab(USceneComponent* TriggerComponent)
{
USceneComponent* CurrentAttachParent = Cast<USceneComponent>(TriggeredComponent->GetAttachParent());
USceneComponent* CurrentAttachParent = Cast<USceneComponent>(TriggerComponent->GetAttachParent());
// We try to release the attached component. If it is not succesful we log and return. Otherwise, we continue.
if (!TryRelease())
......@@ -106,24 +186,7 @@ void UGrabBehavior::OnActionEnd(USceneComponent* TriggeredComponent, const UInpu
Interactable->ResetRestrictInteraction();
}
}
}
bool UGrabBehavior::TryRelease()
{
if (!bObjectGrabbed)
{
return false;
}
if (MyPhysicsComponent)
{
MyPhysicsComponent->DetachFromComponent(FDetachmentTransformRules::KeepWorldTransform);
MyPhysicsComponent->SetSimulatePhysics(bWasSimulatingPhysics);
}
else
{
GetOwner()->GetRootComponent()->DetachFromComponent(FDetachmentTransformRules::KeepWorldTransform);
}
bObjectGrabbed = false;
return true;
// If our attach parent has a collision handling component, remove
HandleCollisionHandlingMovement(CurrentAttachParent, InteractionEnd);
}
......@@ -3,14 +3,13 @@
#include "Interaction/Interactables/HoverBehaviour.h"
void UHoverBehaviour::OnHoverStart(const USceneComponent* TriggeredComponent, FHitResult Hit) {}
void UHoverBehaviour::OnHoverEnd(const USceneComponent* TriggeredComponent) {}
void UHoverBehaviour::OnHoverEvent(const USceneComponent* TriggerComponent, EInteractionEventType EventType,
const FHitResult& Hit)
{
}
void UHoverBehaviour::BeginPlay()
{
Super::BeginPlay();
OnHoverStartEvent.AddDynamic(this, &UHoverBehaviour::OnHoverStart);
OnHoverEndEvent.AddDynamic(this, &UHoverBehaviour::OnHoverEnd);
OnHoverEventEvent.AddDynamic(this, &UHoverBehaviour::OnHoverEvent);
}
......@@ -62,7 +62,8 @@ void UIntenSelectable::HandleOnSelectStartEvents(const UIntenSelectComponent* In
{
for (const UHoverBehaviour* CurrentHoverBehaviour : OnHoverBehaviours)
{
CurrentHoverBehaviour->OnHoverStartEvent.Broadcast(IntenSelect, HitResult);
CurrentHoverBehaviour->OnHoverEventEvent.Broadcast(IntenSelect, EInteractionEventType::InteractionStart,
HitResult);
}
}
......@@ -70,7 +71,9 @@ void UIntenSelectable::HandleOnSelectEndEvents(const UIntenSelectComponent* Inte
{
for (const UHoverBehaviour* CurrentHoverBehaviour : OnHoverBehaviours)
{
CurrentHoverBehaviour->OnHoverEndEvent.Broadcast(IntenSelect);
FHitResult EmptyHit;
CurrentHoverBehaviour->OnHoverEventEvent.Broadcast(IntenSelect, EInteractionEventType::InteractionEnd,
EmptyHit);
}
}
......@@ -79,8 +82,8 @@ void UIntenSelectable::HandleOnClickStartEvents(UIntenSelectComponent* IntenSele
for (const UActionBehaviour* CurrentActionBehaviour : OnActionBehaviours)
{
FInputActionValue EmptyInputActionValue{};
const UInputAction* EmptyInputAction{};
CurrentActionBehaviour->OnActionBeginEvent.Broadcast(IntenSelect, EmptyInputAction, EmptyInputActionValue);
CurrentActionBehaviour->OnActionEventEvent.Broadcast(IntenSelect, EInteractionEventType::InteractionStart,
EmptyInputActionValue);
}
}
......@@ -88,8 +91,8 @@ void UIntenSelectable::HandleOnClickEndEvents(UIntenSelectComponent* IntenSelect
{
for (const UActionBehaviour* CurrentActionBehaviour : OnActionBehaviours)
{
const UInputAction* EmptyInputActionValue{};
CurrentActionBehaviour->OnActionEndEvent.Broadcast(IntenSelect, EmptyInputActionValue, InputValue);
CurrentActionBehaviour->OnActionEventEvent.Broadcast(IntenSelect, EInteractionEventType::InteractionEnd,
InputValue);
}
}
......
......@@ -4,6 +4,9 @@
#include "Interaction/Interactables/InteractableComponent.h"
#include "Interaction/Interactables/ActionBehaviour.h"
#include "Interaction/Interactables/HoverBehaviour.h"
#include "Interaction/Interactors/UBaseInteractionComponent.h"
#include "Logging/StructuredLog.h"
#include "Utility/RWTHVRUtilities.h"
void UInteractableComponent::RestrictInteractionToComponents(const TArray<USceneComponent*>& Components)
{
......@@ -39,9 +42,8 @@ void UInteractableComponent::BeginPlay()
InitDefaultBehaviourReferences();
}
// This functions dispatches the HoverStart Event to the attached Hover Behaviour Components
void UInteractableComponent::HandleOnHoverStartEvents(USceneComponent* TriggerComponent,
const EInteractorType Interactor)
void UInteractableComponent::HandleOnHoverEvents(USceneComponent* TriggerComponent, const EInteractorType Interactor,
const EInteractionEventType EventType)
{
// We early return if there the InteractorFilter is set and the Interactor is allowed.
if (!(InteractorFilter == EInteractorType::None || InteractorFilter & Interactor))
......@@ -52,34 +54,47 @@ void UInteractableComponent::HandleOnHoverStartEvents(USceneComponent* TriggerCo
return;
// Broadcast event to all HoverBehaviours
for (const UHoverBehaviour* b : OnHoverBehaviours)
for (UHoverBehaviour* HoverBehaviour : OnHoverBehaviours)
{
b->OnHoverStartEvent.Broadcast(TriggerComponent, HitResult);
}
}
// This functions dispatches the HoverEnd Event to the attached Hover Behaviour Components
void UInteractableComponent::HandleOnHoverEndEvents(USceneComponent* TriggerComponent, const EInteractorType Interactor)
// Check if we need to replicate the action to the server
if (HoverBehaviour->bExecuteOnServer)
{
// We early return if there the InteractorFilter is set and the Interactor is allowed.
if (!(InteractorFilter == EInteractorType::None || InteractorFilter & Interactor))
return;
// Request the server to execute our behaviour.
// As we can only execute RPCs from an owned object, and we don't necessarily own this actor, pipe it
// through the interactor. Because behaviours can also be triggered from non-interactors, only do this on a
// successful cast
// We early return if the source Interactor is not part of the allowed components
if (!IsComponentAllowed(TriggerComponent))
auto* InteractorComponent = Cast<UUBaseInteractionComponent>(TriggerComponent);
if (!InteractorComponent)
{
UE_LOGFMT(Toolkit, Warning,
"Interaction: TriggerComponent {TriggerComponent} is not a UUBaseInteractionComponent. Only "
"UUBaseInteractionComponent TriggerComponents can be replicated.",
TriggerComponent->GetName());
return;
}
InteractorComponent->RequestHoverBehaviourReplicationStart(HoverBehaviour, EventType, HitResult);
// Broadcast event to all HoverBehaviours
for (const UHoverBehaviour* b : OnHoverBehaviours)
// Broadcast local callback
HoverBehaviour->OnHoverReplicationStartedOriginatorEvent.Broadcast(TriggerComponent, EventType, HitResult);
}
else if (HoverBehaviour->bExecuteOnAllClients)
{
b->OnHoverEndEvent.Broadcast(TriggerComponent);
UE_LOGFMT(Toolkit, Warning,
"Interaction: Behaviour {BehaviourName} has bExecuteOnAllClients=true, which requires "
"bExecuteOnServer also set to true, which is not the case.",
HoverBehaviour->GetName());
}
else // skip replication altogether (default case)
{
HoverBehaviour->OnHoverEventEvent.Broadcast(TriggerComponent, EventType, HitResult);
}
}
}
// This functions dispatches the ActionStart Event to the attached Action Behaviour Components
void UInteractableComponent::HandleOnActionStartEvents(USceneComponent* TriggerComponent,
const UInputAction* InputAction, const FInputActionValue& Value,
const EInteractorType Interactor)
void UInteractableComponent::HandleOnActionEvents(USceneComponent* TriggerComponent, const EInteractorType Interactor,
const EInteractionEventType EventType, const FInputActionValue& Value)
{
// We early return if there the InteractorFilter is set and the Interactor is allowed.
if (!(InteractorFilter == EInteractorType::None || InteractorFilter & Interactor))
......@@ -90,28 +105,41 @@ void UInteractableComponent::HandleOnActionStartEvents(USceneComponent* TriggerC
return;
// Broadcast event to all ActionBehaviours
for (const UActionBehaviour* b : OnActionBehaviours)
for (UActionBehaviour* ActionBehaviour : OnActionBehaviours)
{
b->OnActionBeginEvent.Broadcast(TriggerComponent, InputAction, Value);
}
}
// This functions dispatches the ActionEnd Event to the attached Action Behaviour Components
void UInteractableComponent::HandleOnActionEndEvents(USceneComponent* TriggerComponent, const UInputAction* InputAction,
const FInputActionValue& Value, const EInteractorType Interactor)
// Check if we need to replicate the action to the server
if (ActionBehaviour->bExecuteOnServer)
{
// We early return if there the InteractorFilter is set and the Interactor is allowed.
if (!(InteractorFilter == EInteractorType::None || InteractorFilter & Interactor))
return;
// Request the server to execute our behaviour.
// As we can only execute RPCs from an owned object, and we don't necessarily own this actor, pipe it
// through the interactor. Because behaviours can also be triggered from non-interactors, only do this on a
// successful cast
// We early return if the source Interactor is not part of the allowed components
if (!IsComponentAllowed(TriggerComponent))
auto* InteractorComponent = Cast<UUBaseInteractionComponent>(TriggerComponent);
if (!InteractorComponent)
{
UE_LOGFMT(Toolkit, Warning,
"Interaction: TriggerComponent {TriggerComponent} is not a UUBaseInteractionComponent. Only "
"UUBaseInteractionComponent TriggerComponents can be replicated.",
TriggerComponent->GetName());
return;
}
InteractorComponent->RequestActionBehaviourReplicationStart(ActionBehaviour, EventType, Value);
// Broadcast event to all ActionBehaviours
for (const UActionBehaviour* b : OnActionBehaviours)
// Broadcast local callback
ActionBehaviour->OnActionReplicationStartedOriginatorEvent.Broadcast(TriggerComponent, EventType, Value);
}
else if (ActionBehaviour->bExecuteOnAllClients)
{
b->OnActionEndEvent.Broadcast(TriggerComponent, InputAction, Value);
UE_LOGFMT(Toolkit, Warning,
"Interaction: Behaviour {BehaviourName} has bExecuteOnAllClients=true, which requires "
"bExecuteOnServer also set to true, which is not the case.",
ActionBehaviour->GetName());
}
else // skip replication altogether (default case)
{
ActionBehaviour->OnActionEventEvent.Broadcast(TriggerComponent, EventType, Value);
}
}
}
......
......@@ -6,6 +6,7 @@
#include "EnhancedInputComponent.h"
#include "Interaction/Interactables/InteractableComponent.h"
#include "Interaction/Interactables/InteractionBitSet.h"
#include "Interaction/Interactables/InteractionEventType.h"
#include "Kismet/GameplayStatics.h"
#include "Logging/StructuredLog.h"
......@@ -30,7 +31,7 @@ void UDirectInteractionComponent::TickComponent(float DeltaTime, ELevelTick Tick
TArray<FHitResult> OutHits;
const ETraceTypeQuery TraceType = UEngineTypes::ConvertToTraceType(ECollisionChannel::ECC_PhysicsBody);
auto DebugTrace = bShowDebugTrace ? EDrawDebugTrace::ForOneFrame : EDrawDebugTrace::None;
const auto DebugTrace = bShowDebugTrace ? EDrawDebugTrace::ForOneFrame : EDrawDebugTrace::None;
UKismetSystemLibrary::SphereTraceMulti(GetWorld(), GetAttachParent()->GetComponentLocation(),
GetAttachParent()->GetComponentLocation(), InteractionSphereRadius,
......@@ -59,7 +60,8 @@ void UDirectInteractionComponent::TickComponent(float DeltaTime, ELevelTick Tick
if (!PreviousInteractableComponentsInRange.Contains(CurrentInteractableComp))
{
PreviousInteractableComponentsInRange.AddUnique(CurrentInteractableComp);
CurrentInteractableComp->HandleOnHoverStartEvents(this, EInteractorType::Direct);
CurrentInteractableComp->HandleOnHoverEvents(this, EInteractorType::Direct,
EInteractionEventType::InteractionStart);
}
}
......@@ -71,7 +73,8 @@ void UDirectInteractionComponent::TickComponent(float DeltaTime, ELevelTick Tick
if (!CurrentInteractableCompsInRange.Contains(PrevInteractableComp))
{
ComponentsToRemove.AddUnique(PrevInteractableComp);
PrevInteractableComp->HandleOnHoverEndEvents(this, EInteractorType::Direct);
PrevInteractableComp->HandleOnHoverEvents(this, EInteractorType::Direct,
EInteractionEventType::InteractionEnd);
}
}
......@@ -97,12 +100,12 @@ void UDirectInteractionComponent::SetupPlayerInput(UInputComponent* PlayerInputC
return;
EI->BindAction(InteractionInputAction, ETriggerEvent::Started, this,
&UDirectInteractionComponent::OnBeginInteraction);
&UDirectInteractionComponent::OnBeginInteractionInputAction);
EI->BindAction(InteractionInputAction, ETriggerEvent::Completed, this,
&UDirectInteractionComponent::OnEndInteraction);
&UDirectInteractionComponent::OnEndInteractionInputAction);
}
void UDirectInteractionComponent::OnBeginInteraction(const FInputActionValue& Value)
void UDirectInteractionComponent::OnBeginInteractionInputAction(const FInputActionValue& Value)
{
const FVector InteractionLocation = GetAttachParent()->GetComponentLocation();
......@@ -115,7 +118,7 @@ void UDirectInteractionComponent::OnBeginInteraction(const FInputActionValue& Va
CurrentInteractableComponentsInRange,
[&](auto Element)
{ return FVector(Element->GetOwner()->GetActorLocation() - InteractionLocation).Size(); });
MinElement->HandleOnActionStartEvents(this, InteractionInputAction, Value, EInteractorType::Direct);
MinElement->HandleOnActionEvents(this, EInteractorType::Direct, EInteractionEventType::InteractionStart, Value);
CurrentlyInteractedComponents = {MinElement};
}
else
......@@ -125,19 +128,21 @@ void UDirectInteractionComponent::OnBeginInteraction(const FInputActionValue& Va
CurrentInteractableComponentsInRange.Num());
for (UInteractableComponent* InteractableComp : CurrentInteractableComponentsInRange)
{
InteractableComp->HandleOnActionStartEvents(this, InteractionInputAction, Value, EInteractorType::Direct);
InteractableComp->HandleOnActionEvents(this, EInteractorType::Direct,
EInteractionEventType::InteractionStart, Value);
CurrentlyInteractedComponents.Add(InteractableComp);
}
}
}
void UDirectInteractionComponent::OnEndInteraction(const FInputActionValue& Value)
void UDirectInteractionComponent::OnEndInteractionInputAction(const FInputActionValue& Value)
{
for (auto& Component : CurrentlyInteractedComponents)
{
if (Component.IsValid())
{
Component->HandleOnActionEndEvents(this, InteractionInputAction, Value, EInteractorType::Direct);
Component->HandleOnActionEvents(this, EInteractorType::Direct, EInteractionEventType::InteractionEnd,
Value);
}
}
CurrentlyInteractedComponents.Empty();
......
......@@ -5,6 +5,7 @@
#include "EnhancedInputComponent.h"
#include "Interaction/Interactables/InteractableComponent.h"
#include "Interaction/Interactables/InteractionEventType.h"
#include "Kismet/KismetSystemLibrary.h"
// Sets default values for this component's properties
......@@ -25,14 +26,13 @@ void URaycastInteractionComponent::TickComponent(float DeltaTime, ELevelTick Tic
UInteractableComponent* NewInteractableComponent = nullptr;
TArray<AActor*> ActorsToIgnore;
FHitResult Hit;
const ETraceTypeQuery TraceType = UEngineTypes::ConvertToTraceType(ECollisionChannel::ECC_PhysicsBody);
FVector TraceStart = GetAttachParent()->GetComponentLocation();
FVector TraceEnd = GetAttachParent()->GetComponentLocation() + TraceLength * GetAttachParent()->GetForwardVector();
const FVector TraceStart = GetAttachParent()->GetComponentLocation();
const FVector TraceEnd =
GetAttachParent()->GetComponentLocation() + TraceLength * GetAttachParent()->GetForwardVector();
auto DebugTrace = bShowDebugTrace ? EDrawDebugTrace::ForOneFrame : EDrawDebugTrace::None;
const auto DebugTrace = bShowDebugTrace ? EDrawDebugTrace::ForOneFrame : EDrawDebugTrace::None;
UKismetSystemLibrary::LineTraceSingle(GetWorld(), TraceStart, TraceEnd, TraceType, true, ActorsToIgnore, DebugTrace,
Hit, true, FColor::Green);
......@@ -53,24 +53,28 @@ void URaycastInteractionComponent::TickComponent(float DeltaTime, ELevelTick Tic
if (CurrentInteractable != PreviousInteractable)
{
if (CurrentInteractable && CurrentInteractable->HasInteractionTypeFlag(EInteractorType::Raycast))
CurrentInteractable->HandleOnHoverStartEvents(this, EInteractorType::Raycast);
CurrentInteractable->HandleOnHoverEvents(this, EInteractorType::Raycast,
EInteractionEventType::InteractionStart);
if (PreviousInteractable && PreviousInteractable->HasInteractionTypeFlag(EInteractorType::Raycast))
PreviousInteractable->HandleOnHoverEndEvents(this, EInteractorType::Raycast);
PreviousInteractable->HandleOnHoverEvents(this, EInteractorType::Raycast,
EInteractionEventType::InteractionEnd);
}
PreviousInteractable = CurrentInteractable;
}
void URaycastInteractionComponent::OnBeginInteraction(const FInputActionValue& Value)
void URaycastInteractionComponent::OnBeginInteractionInputAction(const FInputActionValue& Value)
{
if (CurrentInteractable && CurrentInteractable->HasInteractionTypeFlag(EInteractorType::Raycast))
CurrentInteractable->HandleOnActionStartEvents(this, InteractionInputAction, Value, EInteractorType::Raycast);
CurrentInteractable->HandleOnActionEvents(this, EInteractorType::Raycast,
EInteractionEventType::InteractionStart, Value);
}
void URaycastInteractionComponent::OnEndInteraction(const FInputActionValue& Value)
void URaycastInteractionComponent::OnEndInteractionInputAction(const FInputActionValue& Value)
{
if (CurrentInteractable && CurrentInteractable->HasInteractionTypeFlag(EInteractorType::Raycast))
CurrentInteractable->HandleOnActionEndEvents(this, InteractionInputAction, Value, EInteractorType::Raycast);
CurrentInteractable->HandleOnActionEvents(this, EInteractorType::Raycast, EInteractionEventType::InteractionEnd,
Value);
}
void URaycastInteractionComponent::SetupPlayerInput(UInputComponent* PlayerInputComponent)
......@@ -86,7 +90,7 @@ void URaycastInteractionComponent::SetupPlayerInput(UInputComponent* PlayerInput
return;
EI->BindAction(InteractionInputAction, ETriggerEvent::Started, this,
&URaycastInteractionComponent::OnBeginInteraction);
&URaycastInteractionComponent::OnBeginInteractionInputAction);
EI->BindAction(InteractionInputAction, ETriggerEvent::Completed, this,
&URaycastInteractionComponent::OnEndInteraction);
&URaycastInteractionComponent::OnEndInteractionInputAction);
}
// Fill out your copyright notice in the Description page of Project Settings.
#include "Interaction/Interactors/UBaseInteractionComponent.h"
#include "Interaction/Interactables/ActionBehaviour.h"
#include "Interaction/Interactables/HoverBehaviour.h"
#include "Logging/StructuredLog.h"
#include "Utility/RWTHVRUtilities.h"
// Sets default values for this component's properties
UUBaseInteractionComponent::UUBaseInteractionComponent()
{
// Set this component to be initialized when the game starts, and to be ticked every frame. You can turn these
// features off to improve performance if you don't need them.
PrimaryComponentTick.bCanEverTick = true;
SetIsReplicatedByDefault(true);
// ...
}
void UUBaseInteractionComponent::SetupPlayerInput(UInputComponent* PlayerInputComponent)
{
IInputExtensionInterface::SetupPlayerInput(PlayerInputComponent);
}
void UUBaseInteractionComponent::OnBeginInteractionInputAction(const FInputActionValue& Value) {}
void UUBaseInteractionComponent::OnEndInteractionInputAction(const FInputActionValue& Value) {}
void UUBaseInteractionComponent::RequestHoverBehaviourReplicationStart(UHoverBehaviour* Behaviour,
const EInteractionEventType EventType,
const FHitResult& Hit)
{
if (GetOwner()->HasLocalNetOwner())
{
if (GetOwner()->HasAuthority())
{
HoverBehaviourReplicationStart(Behaviour, EventType, Hit);
}
else
{
// RPC
ServerRequestHoverBehaviourReplicationStartRpc(Behaviour, EventType, Hit);
}
}
else
{
UE_LOGFMT(Toolkit, Error,
"Interaction: Trying to replicate HoverBehaviour {HoverBehaviour} in InteractionComponent "
"{InteractionComponent} which has no local net owner!",
Behaviour->GetName(), this->GetName());
}
}
void UUBaseInteractionComponent::HoverBehaviourReplicationStart(UHoverBehaviour* Behaviour,
const EInteractionEventType EventType,
const FHitResult& Hit)
{
if (!Behaviour->bExecuteOnServer) // this should never happen
{
UE_LOGFMT(Toolkit, Error,
"Interaction: Trying to execute HoverBehaviour {HoverBehaviour} in InteractionComponent "
"{InteractionComponent} on the server, but bExecuteOnServer is false!",
Behaviour->GetName(), this->GetName());
return;
}
// If desired, multicast to all clients (including originator)
if (Behaviour->bExecuteOnAllClients)
{
MulticastHoverBehaviourReplicationStartRpc(Behaviour, EventType, Hit);
}
else
{
// Execute the behaviour only on the server
Behaviour->OnHoverEventEvent.Broadcast(this, EventType, Hit);
}
}
void UUBaseInteractionComponent::ServerRequestHoverBehaviourReplicationStartRpc_Implementation(
UHoverBehaviour* Behaviour, const EInteractionEventType EventType, const FHitResult& Hit)
{
HoverBehaviourReplicationStart(Behaviour, EventType, Hit);
}
void UUBaseInteractionComponent::MulticastHoverBehaviourReplicationStartRpc_Implementation(
UHoverBehaviour* Behaviour, const EInteractionEventType EventType, const FHitResult& Hit)
{
Behaviour->OnHoverEventEvent.Broadcast(this, EventType, Hit);
}
void UUBaseInteractionComponent::RequestActionBehaviourReplicationStart(UActionBehaviour* Behaviour,
const EInteractionEventType EventType,
const FInputActionValue& Value)
{
if (GetOwner()->HasLocalNetOwner())
{
if (GetOwner()->HasAuthority())
{
ActionBehaviourReplicationStart(Behaviour, EventType, Value);
}
else
{
// RPC
ServerRequestActionBehaviourReplicationStartRpc(Behaviour, EventType, Value);
}
}
else
{
UE_LOGFMT(Toolkit, Error,
"Interaction: Trying to replicate HoverBehaviour {HoverBehaviour} in InteractionComponent "
"{InteractionComponent} which has no local net owner!",
Behaviour->GetName(), this->GetName());
}
}
void UUBaseInteractionComponent::ActionBehaviourReplicationStart(UActionBehaviour* Behaviour,
const EInteractionEventType EventType,
const FInputActionValue& Value)
{
if (!Behaviour->bExecuteOnServer) // this should never happen
{
UE_LOGFMT(Toolkit, Error,
"Interaction: Trying to execute ActionBehaviour {ActionBehaviour} in InteractionComponent "
"{InteractionComponent} on the server, but bExecuteOnServer is false!",
Behaviour->GetName(), this->GetName());
return;
}
// If desired, multicast to all clients (including originator)
if (Behaviour->bExecuteOnAllClients)
{
MulticastActionBehaviourReplicationStartRpc(Behaviour, EventType, Value);
}
else
{
// Execute the behaviour only on the server
Behaviour->OnActionEventEvent.Broadcast(this, EventType, Value);
}
}
void UUBaseInteractionComponent::ServerRequestActionBehaviourReplicationStartRpc_Implementation(
UActionBehaviour* Behaviour, const EInteractionEventType EventType, const FInputActionValue& Value)
{
ActionBehaviourReplicationStart(Behaviour, EventType, Value);
}
void UUBaseInteractionComponent::MulticastActionBehaviourReplicationStartRpc_Implementation(
UActionBehaviour* Behaviour, const EInteractionEventType EventType, const FInputActionValue& Value)
{
Behaviour->OnActionEventEvent.Broadcast(this, EventType, Value);
}
#include "Pawn/Navigation/CollisionHandlingMovement.h"
#include "Kismet/KismetSystemLibrary.h"
#include "Logging/StructuredLog.h"
#include "Utility/RWTHVRUtilities.h"
UCollisionHandlingMovement::UCollisionHandlingMovement(const FObjectInitializer& ObjectInitializer) :
Super(ObjectInitializer)
......@@ -32,6 +34,15 @@ void UCollisionHandlingMovement::BeginPlay()
void UCollisionHandlingMovement::TickComponent(float DeltaTime, enum ELevelTick TickType,
FActorComponentTickFunction* ThisTickFunction)
{
if (ShouldSkipUpdate(DeltaTime))
{
return;
}
const AController* Controller = PawnOwner->GetController();
if (Controller && Controller->IsLocalController())
{
SetCapsuleColliderToUserSize();
......@@ -50,7 +61,6 @@ void UCollisionHandlingMovement::TickComponent(float DeltaTime, enum ELevelTick
AddInputVector(InputVector);
}
if (NavigationMode == EVRNavigationModes::NAV_FLY || NavigationMode == EVRNavigationModes::NAV_WALK)
{
// if me managed to get into a collision revert the movement since last Tick
......@@ -70,14 +80,20 @@ void UCollisionHandlingMovement::TickComponent(float DeltaTime, enum ELevelTick
}
}
// in case we are in a collision and collision checks are temporarily deactivated.
if (!bCollisionChecksTemporarilyDeactivated)
// in case we are in a collision and collision checks are temporarily deactivated, we only allow physical
// movement without any checks, otherwise check collision during physical movement
if (bCollisionChecksTemporarilyDeactivated)
{
ConsumeInputVector();
}
else
{
// so we add stepping-up (for both walk and fly)
// and gravity for walking only
MoveByGravityOrStepUp(DeltaTime);
// if we physically (in the tracking space) walked into something, move the world away (by moving the pawn)
// if we physically (in the tracking space) walked into something, move the world away (by moving the
// pawn)
CheckForPhysWalkingCollision();
}
}
......@@ -87,6 +103,7 @@ void UCollisionHandlingMovement::TickComponent(float DeltaTime, enum ELevelTick
// just remove whatever input is there
ConsumeInputVector();
}
}
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
}
......@@ -100,6 +117,34 @@ void UCollisionHandlingMovement::SetHeadComponent(USceneComponent* NewHeadCompon
CapsuleColliderComponent->SetWorldLocation(FVector(0.0f, 0.0f, -HalfHeight));
}
bool UCollisionHandlingMovement::AddActorToIgnore(AActor* ActorToIgnore)
{
if (ActorToIgnore && IsValid(ActorToIgnore))
{
ActorsToIgnore.AddUnique(ActorToIgnore);
return true;
}
else
{
UE_LOGFMT(Toolkit, Warning, "UCollisionHandlingMovement::AddActorToIgnore: Cannot add invalid actor");
return false;
}
}
bool UCollisionHandlingMovement::RemoveActorFromIgnore(AActor* ActorToIgnore)
{
if (ActorToIgnore && IsValid(ActorToIgnore))
{
const int32 NumRemoved = ActorsToIgnore.Remove(ActorToIgnore);
return NumRemoved > 0;
}
else
{
UE_LOGFMT(Toolkit, Warning, "UCollisionHandlingMovement::RemoveActorFromIgnore: Cannot remove invalid actor");
return false;
}
}
void UCollisionHandlingMovement::SetCapsuleColliderToUserSize() const
{
// the collider should be placed
......
......@@ -3,21 +3,18 @@
#pragma once
#include "CoreMinimal.h"
#include "InputAction.h"
#include "BaseBehaviour.h"
#include "Components/SceneComponent.h"
#include "InputActionValue.h"
#include "InteractionBitSet.h"
#include "ActionBehaviour.generated.h"
enum EInteractionEventType : uint8;
DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FOnActionBegin, USceneComponent*, TriggeredComponent,
const UInputAction*, InputAction, const FInputActionValue&, Value);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FOnActionEnd, USceneComponent*, TriggeredComponent, const UInputAction*,
InputAction, const FInputActionValue&, Value);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FOnActionBegin, USceneComponent*, TriggerComponent,
const EInteractionEventType, EventType, const FInputActionValue&, Value);
UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent))
class RWTHVRTOOLKIT_API UActionBehaviour : public USceneComponent
class RWTHVRTOOLKIT_API UActionBehaviour : public UBaseBehaviour
{
GENERATED_BODY()
......@@ -26,22 +23,23 @@ public:
UActionBehaviour();
UPROPERTY(BlueprintAssignable)
FOnActionBegin OnActionBeginEvent;
FOnActionBegin OnActionEventEvent;
/**
* Replication specific:
* This is only executed on the local client which processed the interaction and requested the replication process
* to be started. Can be used e.g. for local effects or things that should be done both on the server and local
* client. Broadcast by UInteractableComponent when the originating client sends a server rpc to start the
* interaction replication.
*/
UPROPERTY(BlueprintAssignable)
FOnActionEnd OnActionEndEvent;
FOnActionBegin OnActionReplicationStartedOriginatorEvent;
protected:
UFUNCTION()
virtual void OnActionStart(USceneComponent* TriggeredComponent, const UInputAction* InputAction,
const FInputActionValue& Value);
protected:
UFUNCTION()
virtual void OnActionEnd(USceneComponent* TriggeredComponent, const UInputAction* InputAction,
virtual void OnActionEvent(USceneComponent* TriggerComponent, const EInteractionEventType EventType,
const FInputActionValue& Value);
virtual void BeginPlay() override;
virtual void TickComponent(float DeltaTime, ELevelTick TickType,
FActorComponentTickFunction* ThisTickFunction) override;
};
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Components/SceneComponent.h"
#include "BaseBehaviour.generated.h"
UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent))
class RWTHVRTOOLKIT_API UBaseBehaviour : public USceneComponent
{
GENERATED_BODY()
public:
/**
* Replication part
*/
/**
* Defines whether this behaviour will be executed on the server instead of the local client.
* If set to true, an RPC is sent to the server and it will not be run locally.
* */
UPROPERTY(EditAnywhere, BlueprintReadWrite)
bool bExecuteOnServer = false;
/**
* Defines whether this behaviour will be executed on all connected clients that are relevant, including the
* local originator client. This only has an effect if bExecuteOnServer is true, as only the server can multicast
* to all other clients.
*/
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (EditCondition = "bExecuteOnServer"))
bool bExecuteOnAllClients = false;
};
......@@ -20,14 +20,13 @@ class RWTHVRTOOLKIT_API UGrabBehavior : public UActionBehaviour
GENERATED_BODY()
public:
UGrabBehavior();
UPROPERTY(EditAnywhere, Category = "Grabbing")
bool bBlockOtherInteractionsWhileGrabbed = true;
virtual void OnActionStart(USceneComponent* TriggeredComponent, const UInputAction* InputAction,
const FInputActionValue& Value) override;
virtual void OnActionEnd(USceneComponent* TriggeredComponent, const UInputAction* InputAction,
const FInputActionValue& Value) override;
UPROPERTY(EditAnywhere, Category = "Grabbing")
bool bIgnoreGrabbedActorInCollisionMovement = true;
/**
* Called after the object was successfully attached to the hand
......@@ -41,13 +40,25 @@ public:
UPROPERTY(BlueprintAssignable)
FOnGrabEnd OnGrabEndEvent;
UPROPERTY()
UPrimitiveComponent* MyPhysicsComponent;
virtual void BeginPlay() override;
UPrimitiveComponent* GetFirstComponentSimulatingPhysics(const AActor* TargetActor);
// recursively goes up the hierarchy and returns the highest parent simulating physics
UPrimitiveComponent* GetHighestParentSimulatingPhysics(UPrimitiveComponent* Comp);
UPROPERTY()
UPrimitiveComponent* MyPhysicsComponent;
UFUNCTION()
void ReplicationOriginaterClientCallback(USceneComponent* TriggerComponent, const EInteractionEventType EventType,
const FInputActionValue& Value);
void HandleCollisionHandlingMovement(const USceneComponent* CurrentAttachParent,
const EInteractionEventType EventType);
virtual void OnActionEvent(USceneComponent* TriggerComponent, const EInteractionEventType EventType,
const FInputActionValue& Value) override;
UFUNCTION(BlueprintPure)
bool IsObjectGrabbed() const { return bObjectGrabbed; }
......@@ -61,7 +72,13 @@ private:
*/
bool TryRelease();
void StartGrab(USceneComponent* TriggerComponent);
void EndGrab(USceneComponent* TriggerComponent);
bool bObjectGrabbed = false;
bool bWasSimulatingPhysics;
bool bWasAddedToIgnore = false;
};
......@@ -3,16 +3,16 @@
#pragma once
#include "CoreMinimal.h"
#include "BaseBehaviour.h"
#include "InteractionEventType.h"
#include "Components/SceneComponent.h"
#include "HoverBehaviour.generated.h"
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnHoverStart, const USceneComponent*, TriggeredComponent, FHitResult,
Hit);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnHoverEnd, const USceneComponent*, TriggeredComponent);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FOnHoverEvent, const USceneComponent*, TriggeredComponent,
const EInteractionEventType, EventType, const FHitResult&, Hit);
UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent))
class RWTHVRTOOLKIT_API UHoverBehaviour : public USceneComponent
class RWTHVRTOOLKIT_API UHoverBehaviour : public UBaseBehaviour
{
GENERATED_BODY()
......@@ -22,16 +22,22 @@ public:
* VRPawn) Hit: Hit Result of the trace to get access to e.g. contact point/normals etc.
*/
UPROPERTY(BlueprintAssignable)
FOnHoverStart OnHoverStartEvent;
FOnHoverEvent OnHoverEventEvent;
/**
* Replication specific:
* This is only executed on the local client which processed the interaction and requested the replication process
* to be started. Can be used e.g. for local effects or things that should be done both on the server and local
* client. Broadcast by UInteractableComponent when the originating client sends a server rpc to start the
* interaction replication.
*/
UPROPERTY(BlueprintAssignable)
FOnHoverEnd OnHoverEndEvent;
FOnHoverEvent OnHoverReplicationStartedOriginatorEvent;
protected:
UFUNCTION()
virtual void OnHoverStart(const USceneComponent* TriggeredComponent, FHitResult Hit);
UFUNCTION()
virtual void OnHoverEnd(const USceneComponent* TriggeredComponent);
virtual void OnHoverEvent(const USceneComponent* TriggerComponent, EInteractionEventType EventType,
const FHitResult& Hit);
virtual void BeginPlay() override;
};
......@@ -9,6 +9,8 @@
#include "InteractableComponent.generated.h"
enum EInteractionEventType : uint8;
class UBaseBehaviour;
struct FInputActionValue;
class UActionBehaviour;
class UHoverBehaviour;
......@@ -53,7 +55,7 @@ public:
bool bAllowInteractionFromChildGeometry = true;
UFUNCTION(BlueprintCallable)
FORCEINLINE bool HasInteractionTypeFlag(EInteractorType type) { return type & InteractorFilter; }
FORCEINLINE bool HasInteractionTypeFlag(EInteractorType Type) { return Type & InteractorFilter; }
/**
* @brief Restrict interactability to given components (e.g. if an object is grabbed, block interactions from other
......@@ -74,12 +76,10 @@ protected:
virtual void BeginPlay() override;
public:
void HandleOnHoverStartEvents(USceneComponent* TriggerComponent, const EInteractorType Interactor);
void HandleOnHoverEndEvents(USceneComponent* TriggerComponent, const EInteractorType Interactor);
void HandleOnActionStartEvents(USceneComponent* TriggerComponent, const UInputAction* InputAction,
const FInputActionValue& Value, const EInteractorType Interactor);
void HandleOnActionEndEvents(USceneComponent* TriggerComponent, const UInputAction* InputAction,
const FInputActionValue& Value, const EInteractorType Interactor);
void HandleOnHoverEvents(USceneComponent* TriggerComponent, const EInteractorType Interactor,
const EInteractionEventType EventType);
void HandleOnActionEvents(USceneComponent* TriggerComponent, const EInteractorType Interactor,
const EInteractionEventType EventType, const FInputActionValue& Value);
/**
* @brief If hover and action behaviors are not explicitly specified, load all existing ones
......
#pragma once
UENUM(BlueprintType)
enum EInteractionEventType : uint8
{
InteractionStart = 0,
InteractionEnd = 1,
};
......@@ -3,13 +3,13 @@
#pragma once
#include "CoreMinimal.h"
#include "UBaseInteractionComponent.h"
#include "Components/SceneComponent.h"
#include "Interaction/Interactables/InteractableComponent.h"
#include "Pawn/InputExtensionInterface.h"
#include "DirectInteractionComponent.generated.h"
UCLASS(Abstract, Blueprintable)
class RWTHVRTOOLKIT_API UDirectInteractionComponent : public USceneComponent, public IInputExtensionInterface
class RWTHVRTOOLKIT_API UDirectInteractionComponent : public UUBaseInteractionComponent
{
GENERATED_BODY()
......@@ -20,29 +20,18 @@ public:
virtual void TickComponent(float DeltaTime, ELevelTick TickType,
FActorComponentTickFunction* ThisTickFunction) override;
UPROPERTY(EditAnywhere, Category = "Input")
class UInputAction* InteractionInputAction;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Direct Interaction")
float InteractionSphereRadius = 15.0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Direct Interaction")
bool bShowDebugTrace = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Direct Interaction")
bool bOnlyInteractWithClosestActor = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Direct Interaction")
TArray<AActor*> ActorsToIgnore;
virtual void SetupPlayerInput(UInputComponent* PlayerInputComponent) override;
private:
UFUNCTION()
void OnBeginInteraction(const FInputActionValue& Value);
virtual void OnBeginInteractionInputAction(const FInputActionValue& Value) override;
UFUNCTION()
void OnEndInteraction(const FInputActionValue& Value);
virtual void OnEndInteractionInputAction(const FInputActionValue& Value) override;
UPROPERTY()
TArray<UInteractableComponent*> PreviousInteractableComponentsInRange;
......
......@@ -2,16 +2,15 @@
#pragma once
#include <Pawn/InputExtensionInterface.h>
#include "CoreMinimal.h"
#include "UBaseInteractionComponent.h"
#include "Components/SceneComponent.h"
#include "Interaction/Interactables/InteractableComponent.h"
#include "RaycastInteractionComponent.generated.h"
UCLASS(Abstract, Blueprintable)
class RWTHVRTOOLKIT_API URaycastInteractionComponent : public USceneComponent, public IInputExtensionInterface
class RWTHVRTOOLKIT_API URaycastInteractionComponent : public UUBaseInteractionComponent
{
GENERATED_BODY()
......@@ -23,20 +22,13 @@ public:
virtual void TickComponent(float DeltaTime, ELevelTick TickType,
FActorComponentTickFunction* ThisTickFunction) override;
UPROPERTY(EditAnywhere, Category = "Input")
class UInputAction* InteractionInputAction;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Raycast")
float TraceLength = 3000.0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Raycast")
bool bShowDebugTrace = false;
private:
UFUNCTION()
void OnBeginInteraction(const FInputActionValue& Value);
virtual void OnBeginInteractionInputAction(const FInputActionValue& Value) override;
UFUNCTION()
void OnEndInteraction(const FInputActionValue& Value);
virtual void OnEndInteractionInputAction(const FInputActionValue& Value) override;
public:
virtual void SetupPlayerInput(UInputComponent* PlayerInputComponent) override;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment