Skip to content
Snippets Groups Projects
Commit 5d6bee08 authored by Daniel Rupp's avatar Daniel Rupp
Browse files

Merge branch 'dev/5.3' into 'dev/5.3'

# Conflicts:
#   Source/RWTHVRToolkit/Public/Interaction/Interactables/GrabBehavior.h
#   Source/RWTHVRToolkit/Public/Interaction/Interactables/InteractableComponent.h
parents a3654dfb 9bd56300
Branches
Tags
2 merge requests!80UE5.3-2023.1-rc2,!56feature(Interaction): improve grabbing
Pipeline #333180 failed
Showing
with 159 additions and 168 deletions
......@@ -73,8 +73,8 @@ void ACAVEOverlayController::CycleDoorType()
void ACAVEOverlayController::HandleClusterEvent(const FDisplayClusterClusterEventJson& Event)
{
if (Event.Category.Equals("CAVEOverlay") && Event.Type.Equals("DoorChange") && Event.Parameters.Contains(
"NewDoorState"))
if (Event.Category.Equals("CAVEOverlay") && Event.Type.Equals("DoorChange") &&
Event.Parameters.Contains("NewDoorState"))
{
SetDoorMode(static_cast<EDoorMode>(FCString::Atoi(*Event.Parameters["NewDoorState"])));
}
......@@ -91,8 +91,7 @@ void ACAVEOverlayController::SetDoorMode(const EDoorMode NewMode)
if (ScreenType == SCREEN_DOOR)
Overlay->BlackBox->SetRenderScale(FVector2D(0, 1));
if (ScreenType == SCREEN_DOOR_PARTIAL)
Overlay->BlackBox->
SetRenderScale(FVector2D(DoorOpeningWidthRelative, 1));
Overlay->BlackBox->SetRenderScale(FVector2D(DoorOpeningWidthRelative, 1));
if (ScreenType == SCREEN_PRIMARY)
Overlay->BlackBox->SetRenderScale(FVector2D(0, 1));
......@@ -178,8 +177,8 @@ void ACAVEOverlayController::BeginPlay()
if (const ULocalPlayer* LocalPlayer = PC->GetLocalPlayer())
{
if (UEnhancedInputLocalPlayerSubsystem* InputSystem = LocalPlayer->GetSubsystem<
UEnhancedInputLocalPlayerSubsystem>())
if (UEnhancedInputLocalPlayerSubsystem* InputSystem =
LocalPlayer->GetSubsystem<UEnhancedInputLocalPlayerSubsystem>())
{
InputSystem->AddMappingContext(IMCCaveOverlayInputMapping, 0);
}
......@@ -190,8 +189,8 @@ void ACAVEOverlayController::BeginPlay()
IDisplayClusterClusterManager* ClusterManager = IDisplayCluster::Get().GetClusterMgr();
if (ClusterManager && !ClusterEventListenerDelegate.IsBound())
{
ClusterEventListenerDelegate = FOnClusterEventJsonListener::CreateUObject(
this, &ACAVEOverlayController::HandleClusterEvent);
ClusterEventListenerDelegate =
FOnClusterEventJsonListener::CreateUObject(this, &ACAVEOverlayController::HandleClusterEvent);
ClusterManager->AddClusterEventJsonListener(ClusterEventListenerDelegate);
}
......@@ -266,38 +265,37 @@ double ACAVEOverlayController::CalculateOpacityFromPosition(const FVector& Posit
// fully opaque when WallFadeDistance away from the wall. Could just use a lerp here..
return FMath::Max(
FMath::Clamp((FMath::Abs(Position.X) - (WallDistance - WallCloseDistance)) / WallFadeDistance, 0.0, 1.0),
FMath::Clamp((FMath::Abs(Position.Y) - (WallDistance - WallCloseDistance)) / WallFadeDistance, 0.0, 1.0)
);
FMath::Clamp((FMath::Abs(Position.Y) - (WallDistance - WallCloseDistance)) / WallFadeDistance, 0.0, 1.0));
}
bool ACAVEOverlayController::PositionInDoorOpening(const FVector& Position) const
{
// The position of the corner with 10cm of buffer. In negative direction because the door is in negative direction of the cave
// The position of the corner with 10cm of buffer. In negative direction because the door is in negative direction
// of the cave
const float CornerValue = -(WallDistance + 10);
// Check whether our X position is within the door zone. This zone starts 10cm further away from the wall
// than the WallCloseDistance, and ends 10cm outside of the wall (door). As the door is in negative X direction,
// the signs need to be negated.
const bool bXWithinDoor = FMath::IsWithinInclusive(Position.X, CornerValue,
-(WallDistance - WallCloseDistance - 10));
const bool bXWithinDoor =
FMath::IsWithinInclusive(Position.X, CornerValue, -(WallDistance - WallCloseDistance - 10));
// Checks whether our Y position is between the lower corner with some overlap and
// the door corner (CornerValue + DoorCurrentOpeningWidthAbsolute)
const bool bYWithinDoor = FMath::IsWithinInclusive(Position.Y, CornerValue,
CornerValue + DoorCurrentOpeningWidthAbsolute);
const bool bYWithinDoor =
FMath::IsWithinInclusive(Position.Y, CornerValue, CornerValue + DoorCurrentOpeningWidthAbsolute);
return bXWithinDoor && bYWithinDoor;
}
void ACAVEOverlayController::SetSignsForHand(UStaticMeshComponent* Sign, const FVector& HandPosition,
UMaterialInstanceDynamic* HandMaterial) const
{
const bool bHandIsCloseToWall = FMath::IsWithinInclusive(HandPosition.GetAbsMax(),
WallDistance - WallCloseDistance, WallDistance);
const bool bHandIsCloseToWall =
FMath::IsWithinInclusive(HandPosition.GetAbsMax(), WallDistance - WallCloseDistance, WallDistance);
if (bHandIsCloseToWall && !PositionInDoorOpening(HandPosition))
{
Sign->SetVisibility(true);
HandMaterial->SetScalarParameterValue("SignOpacity",
CalculateOpacityFromPosition(HandPosition));
HandMaterial->SetScalarParameterValue("SignOpacity", CalculateOpacityFromPosition(HandPosition));
// Which wall are we closest to? This is the wall we project the sign onto
const bool bXWallCloser = FMath::Abs(HandPosition.X) > FMath::Abs(HandPosition.Y);
......@@ -330,8 +328,8 @@ void ACAVEOverlayController::Tick(float DeltaTime)
// Head/Tape Logic
const FVector HeadPosition = VRPawn->HeadCameraComponent->GetRelativeTransform().GetLocation();
const bool bHeadIsCloseToWall = FMath::IsWithinInclusive(HeadPosition.GetAbsMax(),
WallDistance - WallCloseDistance, WallDistance);
const bool bHeadIsCloseToWall =
FMath::IsWithinInclusive(HeadPosition.GetAbsMax(), WallDistance - WallCloseDistance, WallDistance);
// Only show the tape when close to a wall and not within the door opening
if (bHeadIsCloseToWall && !PositionInDoorOpening(HeadPosition))
......
......@@ -9,9 +9,11 @@ void FClusterConsole::Register()
ClusterConsoleCommand = IConsoleManager::Get().RegisterConsoleCommand(
TEXT("ClusterExecute"),
TEXT("<Your Command> - Execute commands on every node of the nDisplay cluster by prepending ClusterExecute"),
FConsoleCommandWithArgsDelegate::CreateLambda([](const TArray<FString>& Args)
FConsoleCommandWithArgsDelegate::CreateLambda(
[](const TArray<FString>& Args)
{
if (IDisplayCluster::Get().GetClusterMgr() == nullptr || Args.Num() == 0) return;
if (IDisplayCluster::Get().GetClusterMgr() == nullptr || Args.Num() == 0)
return;
/* Emitting cluster event */
FDisplayClusterClusterEventJson ClusterEvent;
......
......@@ -2,15 +2,9 @@
#define LOCTEXT_NAMESPACE "FRWTHVRClusterModule"
void FRWTHVRClusterModule::StartupModule()
{
ClusterConsole.Register();
}
void FRWTHVRClusterModule::StartupModule() { ClusterConsole.Register(); }
void FRWTHVRClusterModule::ShutdownModule()
{
ClusterConsole.Unregister();
}
void FRWTHVRClusterModule::ShutdownModule() { ClusterConsole.Unregister(); }
#undef LOCTEXT_NAMESPACE
......
......@@ -44,19 +44,24 @@ private:
EScreen_Type ScreenType = SCREEN_NORMAL;
// which additional node names define the screens that cover the door
const TArray<FString> ScreensDoor = {
"node_bul_left_eye", "node_bul_right_eye", "node_bll_left_eye", "node_bll_right_eye"
};
const TArray<FString> ScreensDoor = {"node_bul_left_eye", "node_bul_right_eye", "node_bll_left_eye",
"node_bll_right_eye"};
// which node names define the screens that cover the partial door
const TArray<FString> ScreensDoorPartial = {
"node_bur_left_eye", "node_bur_right_eye", "node_blr_left_eye", "node_blr_right_eye"
};
const TArray<FString> ScreensDoorPartial = {"node_bur_left_eye", "node_bur_right_eye", "node_blr_left_eye",
"node_blr_right_eye"};
const FString ScreenMain = "node_main";
// Door Mode
enum EDoorMode { DOOR_PARTIALLY_OPEN = 0, DOOR_OPEN = 1, DOOR_CLOSED = 2, DOOR_DEBUG = 3, DOOR_NUM_MODES = 4 };
enum EDoorMode
{
DOOR_PARTIALLY_OPEN = 0,
DOOR_OPEN = 1,
DOOR_CLOSED = 2,
DOOR_DEBUG = 3,
DOOR_NUM_MODES = 4
};
const FString DoorModeNames[DOOR_NUM_MODES] = {"Partially Open", "Open", "Closed", "Debug"};
EDoorMode DoorCurrentMode = DOOR_PARTIALLY_OPEN;
......
......@@ -9,7 +9,8 @@
* The ClusterConsole provides the console command "ClusterExecute"
* The code catches your command, broadcasts it to every nDisplay node and executes it everywhere
*
* This class has to be registered and unregistered. This can easily be done in every StartupModule/ShutdownModule functions.
* This class has to be registered and unregistered. This can easily be done in every StartupModule/ShutdownModule
* functions.
*/
USTRUCT()
struct RWTHVRCLUSTER_API FClusterConsole
......
......@@ -14,18 +14,17 @@ inline void SerializeParameters(FMemoryWriter* MemoryWriter, ParameterType&& Par
SerializeParameters(MemoryWriter, Forward<RemainingParameterTypes>(RemainingParameters)...);
}
inline void SerializeParameters(FMemoryWriter* MemoryWriter)
{
}
inline void SerializeParameters(FMemoryWriter* MemoryWriter) {}
// This is a wrapper function to recursively fill the argument tuple. This overload is only used if the index indicating the
// currently handled attribute is less than the number of total attributes. I.e., if the attribute index is valid.
// This is a wrapper function to recursively fill the argument tuple. This overload is only used if the index indicating
// the currently handled attribute is less than the number of total attributes. I.e., if the attribute index is valid.
template <int CurrentIndex, typename... ArgTypes>
inline typename TEnableIf<(CurrentIndex < sizeof...(ArgTypes))>::Type
FillArgumentTuple(FMemoryReader* MemoryReader, TTuple<ArgTypes...>* ArgumentTuple)
{
// Read the "<<" as ">>" operator here. FArchive uses the same for both and decides based on an internal type on what to do. So
// this statement parses the bytes that were passed into reader and puts the parsed object into the tuple at index CurrentIndex.
// Read the "<<" as ">>" operator here. FArchive uses the same for both and decides based on an internal type on
// what to do. So this statement parses the bytes that were passed into reader and puts the parsed object into the
// tuple at index CurrentIndex.
(*MemoryReader) << ArgumentTuple->template Get<CurrentIndex>();
// Recursive call for the remaining attributes.
......@@ -40,20 +39,18 @@ FillArgumentTuple(FMemoryReader* MemoryReader, TTuple<ArgTypes...>* ArgumentTupl
}
template <typename RetType, typename... ArgTypes>
inline RetType CallDelegateWithParameterMap(
const TDelegate<RetType, ArgTypes...>& Delegate, const TMap<FString, FString>& Parameters)
inline RetType CallDelegateWithParameterMap(const TDelegate<RetType, ArgTypes...>& Delegate,
const TMap<FString, FString>& Parameters)
{
// Create a tuple that holds all arguments. This assumes that all argument types are default constructible. However, all
// types that overload the FArchive "<<" operator probably are.
// Create a tuple that holds all arguments. This assumes that all argument types are default constructible. However,
// all types that overload the FArchive "<<" operator probably are.
TTuple<typename std::remove_cv_t<typename TRemoveReference<ArgTypes>::Type>...> ArgumentTuple;
// This call will parse the string map and fill all values in the tuple appropriately.
FillArgumentTuple<0>(&ArgumentTuple, Parameters);
// The lambda function is only necessary because delegates do not overload the ()-operator but use the Execute() method
// instead. So, the lambda acts as a wrapper.
// The lambda function is only necessary because delegates do not overload the ()-operator but use the Execute()
// method instead. So, the lambda acts as a wrapper.
return ArgumentTuple.ApplyBefore([Delegate](ArgTypes&&... Arguments)
{
Delegate.Execute(Forward<ArgTypes>(Arguments)...);
});
{ Delegate.Execute(Forward<ArgTypes>(Arguments)...); });
}
......@@ -11,8 +11,8 @@ static constexpr int32 CLUSTER_EVENT_WRAPPER_EVENT_ID = 1337420;
template <typename MemberFunctionType, MemberFunctionType MemberFunction>
class ClusterEventWrapperEvent;
template <typename ObjectType, typename ReturnType, typename... ArgTypes, ReturnType (ObjectType::*
MemberFunction)(ArgTypes...)>
template <typename ObjectType, typename ReturnType, typename... ArgTypes,
ReturnType (ObjectType::*MemberFunction)(ArgTypes...)>
class ClusterEventWrapperEvent<ReturnType (ObjectType::*)(ArgTypes...), MemberFunction>
{
static_assert(TIsDerivedFrom<ObjectType, UObject>::IsDerived, "Object needs to derive from UObject");
......@@ -20,9 +20,7 @@ class ClusterEventWrapperEvent<ReturnType (ObjectType::*)(ArgTypes...), MemberFu
public:
using MemberFunctionType = decltype(MemberFunction);
ClusterEventWrapperEvent(const TCHAR* MethodName) : MethodName{MethodName}
{
}
ClusterEventWrapperEvent(const TCHAR* MethodName) : MethodName{MethodName} {}
void Attach(ObjectType* NewObject)
{
......@@ -74,9 +72,7 @@ public:
FillArgumentTuple<0>(&MemoryReader, &ArgumentTuple);
ArgumentTuple.ApplyBefore([this](const ArgTypes&... Arguments)
{
(Object->*MemberFunction)(Forward<const ArgTypes&>(Arguments)...);
});
{ (Object->*MemberFunction)(Forward<const ArgTypes&>(Arguments)...); });
});
ClusterManager->AddClusterEventBinaryListener(ClusterEventListenerDelegate);
}
......@@ -135,7 +131,8 @@ private:
#define DCEW_TOSTRING(x) DCEW_STRINGIFY(x)
#define DECLARE_DISPLAY_CLUSTER_EVENT(OwningType, MethodIdentifier) \
ClusterEventWrapperEvent<decltype(&OwningType::MethodIdentifier), &OwningType::MethodIdentifier> MethodIdentifier##Event \
ClusterEventWrapperEvent<decltype(&OwningType::MethodIdentifier), &OwningType::MethodIdentifier> \
MethodIdentifier##Event \
{ \
TEXT(DCEW_TOSTRING(OwningType) DCEW_TOSTRING(MethodIdentifier)) \
}
......@@ -34,9 +34,8 @@ FString ARWTHVRGameModeBase::InitNewPlayer(APlayerController* NewPlayerControlle
? UGameplayStatics::ParseOption(Options, NodeNameKey)
: PrimaryNodeId;
const EPlayerType Type = NodeName == PrimaryNodeId
? EPlayerType::nDisplayPrimary
: EPlayerType::nDisplaySecondary;
const EPlayerType Type =
NodeName == PrimaryNodeId ? EPlayerType::nDisplayPrimary : EPlayerType::nDisplaySecondary;
State->RequestSetPlayerType(Type);
}
}
......
......@@ -4,7 +4,8 @@
void FActivateConsoleInShipping::Register()
{
/* Should only enable console in shipping */
if (FApp::GetBuildConfiguration() != EBuildConfiguration::Shipping) return;
if (FApp::GetBuildConfiguration() != EBuildConfiguration::Shipping)
return;
On_Post_World_Initialization_Delegate.BindRaw(this, &FActivateConsoleInShipping::OnSessionStart);
StartHandle = FWorldDelegates::OnPostWorldInitialization.Add(On_Post_World_Initialization_Delegate);
......@@ -12,7 +13,8 @@ void FActivateConsoleInShipping::Register()
void FActivateConsoleInShipping::Unregister() const
{
if (FApp::GetBuildConfiguration() != EBuildConfiguration::Shipping) return;
if (FApp::GetBuildConfiguration() != EBuildConfiguration::Shipping)
return;
FWorldDelegates::OnPostWorldInitialization.Remove(StartHandle);
}
......
......@@ -4,10 +4,7 @@
#include "Interaction/Interactables/ActionBehaviour.h"
// We disable ticking here, as we are mainly interested in the events
UActionBehaviour::UActionBehaviour()
{
PrimaryComponentTick.bCanEverTick = false;
}
UActionBehaviour::UActionBehaviour() { PrimaryComponentTick.bCanEverTick = false; }
void UActionBehaviour::OnActionStart(USceneComponent* TriggeredComponent, const UInputAction* InputAction,
const FInputActionValue& Value)
......
......@@ -3,13 +3,9 @@
#include "Interaction/Interactables/HoverBehaviour.h"
void UHoverBehaviour::OnHoverStart(const USceneComponent* TriggeredComponent, FHitResult Hit)
{
}
void UHoverBehaviour::OnHoverStart(const USceneComponent* TriggeredComponent, FHitResult Hit) {}
void UHoverBehaviour::OnHoverEnd(const USceneComponent* TriggeredComponent)
{
}
void UHoverBehaviour::OnHoverEnd(const USceneComponent* TriggeredComponent) {}
void UHoverBehaviour::BeginPlay()
{
......
......@@ -44,10 +44,12 @@ void UInteractableComponent::HandleOnHoverStartEvents(USceneComponent* TriggerCo
const EInteractorType Interactor)
{
// We early return if there the InteractorFilter is set and the Interactor is allowed.
if (!(InteractorFilter == EInteractorType::None || InteractorFilter & Interactor)) return;
if (!(InteractorFilter == EInteractorType::None || InteractorFilter & Interactor))
return;
// We early return if the source Interactor is not part of the allowed components
if (!IsComponentAllowed(TriggerComponent)) return;
if (!IsComponentAllowed(TriggerComponent))
return;
// Broadcast event to all HoverBehaviours
for (const UHoverBehaviour* b : OnHoverBehaviours)
......@@ -60,10 +62,12 @@ void UInteractableComponent::HandleOnHoverStartEvents(USceneComponent* TriggerCo
void UInteractableComponent::HandleOnHoverEndEvents(USceneComponent* TriggerComponent, const EInteractorType Interactor)
{
// We early return if there the InteractorFilter is set and the Interactor is allowed.
if (!(InteractorFilter == EInteractorType::None || InteractorFilter & Interactor)) return;
if (!(InteractorFilter == EInteractorType::None || InteractorFilter & Interactor))
return;
// We early return if the source Interactor is not part of the allowed components
if (!IsComponentAllowed(TriggerComponent)) return;
if (!IsComponentAllowed(TriggerComponent))
return;
// Broadcast event to all HoverBehaviours
for (const UHoverBehaviour* b : OnHoverBehaviours)
......@@ -74,15 +78,16 @@ void UInteractableComponent::HandleOnHoverEndEvents(USceneComponent* TriggerComp
// This functions dispatches the ActionStart Event to the attached Action Behaviour Components
void UInteractableComponent::HandleOnActionStartEvents(USceneComponent* TriggerComponent,
const UInputAction* InputAction,
const FInputActionValue& Value,
const UInputAction* InputAction, const FInputActionValue& Value,
const EInteractorType Interactor)
{
// We early return if there the InteractorFilter is set and the Interactor is allowed.
if (!(InteractorFilter == EInteractorType::None || InteractorFilter & Interactor)) return;
if (!(InteractorFilter == EInteractorType::None || InteractorFilter & Interactor))
return;
// We early return if the source Interactor is not part of the allowed components
if (!IsComponentAllowed(TriggerComponent)) return;
if (!IsComponentAllowed(TriggerComponent))
return;
// Broadcast event to all ActionBehaviours
for (const UActionBehaviour* b : OnActionBehaviours)
......@@ -93,14 +98,15 @@ void UInteractableComponent::HandleOnActionStartEvents(USceneComponent* TriggerC
// 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)
const FInputActionValue& Value, const EInteractorType Interactor)
{
// We early return if there the InteractorFilter is set and the Interactor is allowed.
if (!(InteractorFilter == EInteractorType::None || InteractorFilter & Interactor)) return;
if (!(InteractorFilter == EInteractorType::None || InteractorFilter & Interactor))
return;
// We early return if the source Interactor is not part of the allowed components
if (!IsComponentAllowed(TriggerComponent)) return;
if (!IsComponentAllowed(TriggerComponent))
return;
// Broadcast event to all ActionBehaviours
for (const UActionBehaviour* b : OnActionBehaviours)
......
......@@ -13,8 +13,8 @@
// Sets default values for this component's properties
UGrabComponent::UGrabComponent()
{
// 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.
// 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;
// ...
......@@ -35,8 +35,7 @@ void UGrabComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorC
UKismetSystemLibrary::SphereTraceMulti(GetWorld(), GetAttachParent()->GetComponentLocation(),
GetAttachParent()->GetComponentLocation(), GrabSphereRadius, TraceType, true,
ActorsToIgnore, DebugTrace,
OutHits, true, FColor::Green);
ActorsToIgnore, DebugTrace, OutHits, true, FColor::Green);
for (FHitResult Hit : OutHits)
{
......
......@@ -11,8 +11,8 @@
// Sets default values for this component's properties
URaycastSelectionComponent::URaycastSelectionComponent()
{
// 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.
// 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;
// ...
......@@ -35,8 +35,7 @@ void URaycastSelectionComponent::TickComponent(float DeltaTime, ELevelTick TickT
auto DebugTrace = bShowDebugTrace ? EDrawDebugTrace::ForOneFrame : EDrawDebugTrace::None;
UKismetSystemLibrary::LineTraceSingle(GetWorld(), TraceStart, TraceEnd
, TraceType, true, ActorsToIgnore, DebugTrace,
UKismetSystemLibrary::LineTraceSingle(GetWorld(), TraceStart, TraceEnd, TraceType, true, ActorsToIgnore, DebugTrace,
Hit, true, FColor::Green);
AActor* HitActor = Hit.GetActor();
......@@ -66,15 +65,13 @@ void URaycastSelectionComponent::TickComponent(float DeltaTime, ELevelTick TickT
void URaycastSelectionComponent::OnBeginSelect(const FInputActionValue& Value)
{
if (CurrentInteractable && CurrentInteractable->HasInteractionTypeFlag(EInteractorType::Raycast))
CurrentInteractable->HandleOnActionStartEvents(this, RayCastSelectInputAction, Value,
EInteractorType::Raycast);
CurrentInteractable->HandleOnActionStartEvents(this, RayCastSelectInputAction, Value, EInteractorType::Raycast);
}
void URaycastSelectionComponent::OnEndSelect(const FInputActionValue& Value)
{
if (CurrentInteractable && CurrentInteractable->HasInteractionTypeFlag(EInteractorType::Raycast))
CurrentInteractable->HandleOnActionEndEvents(this, RayCastSelectInputAction, Value,
EInteractorType::Raycast);
CurrentInteractable->HandleOnActionEndEvents(this, RayCastSelectInputAction, Value, EInteractorType::Raycast);
}
void URaycastSelectionComponent::SetupPlayerInput(UInputComponent* PlayerInputComponent)
......
......@@ -3,7 +3,8 @@
#include "Pawn/InputExtensionInterface.h"
UEnhancedInputLocalPlayerSubsystem* IInputExtensionInterface::GetEnhancedInputLocalPlayerSubsystem(const APawn* Pawn) const
UEnhancedInputLocalPlayerSubsystem*
IInputExtensionInterface::GetEnhancedInputLocalPlayerSubsystem(const APawn* Pawn) const
{
const APlayerController* PlayerController = Pawn ? Cast<APlayerController>(Pawn->GetController()) : nullptr;
const ULocalPlayer* LP = PlayerController ? PlayerController->GetLocalPlayer() : nullptr;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment