diff --git a/Source/RWTHVRToolkit/Private/Pawn/RWTHVRPawn.cpp b/Source/RWTHVRToolkit/Private/Pawn/RWTHVRPawn.cpp index 812e83ea74b96709e72b7768dbbd5d90bc041f52..4eb03b04e7bfdb3b83eb0d88a70a138efdb68aba 100644 --- a/Source/RWTHVRToolkit/Private/Pawn/RWTHVRPawn.cpp +++ b/Source/RWTHVRToolkit/Private/Pawn/RWTHVRPawn.cpp @@ -41,8 +41,30 @@ ARWTHVRPawn::ARWTHVRPawn(const FObjectInitializer& ObjectInitializer) : Super(Ob LeftHand = CreateDefaultSubobject<UReplicatedMotionControllerComponent>(TEXT("Left Hand MCC")); LeftHand->SetupAttachment(RootComponent); + + GetRootComponent()->TransformUpdated.AddLambda([this](USceneComponent*, EUpdateTransformFlags, ETeleportType) + { + FVector CurrentScale = this->GetActorScale3D(); + if (CurrentScale.X == CurrentScale.Y && CurrentScale.Y == CurrentScale.Z) + { + float expectedScale = GetWorldSettings()->WorldToMeters / InitialWorldToMeters; + float ErrorPrecision = 1E-05; + if (FMath::IsNearlyEqual(CurrentScale.X, expectedScale, ErrorPrecision)) + { + return; + } + } + UE_LOGFMT(Toolkit, Warning, + "ARWTHVRPawn: Do not adjust the scale of the pawn directly. This will not work in VR. Use ARWTHVRPawn::SetScale(float) instead.") + ; + }); +} + +void ARWTHVRPawn::BeginPlay() +{ + Super::BeginPlay(); + InitialWorldToMeters = GetWorldSettings()->WorldToMeters; } -void ARWTHVRPawn::BeginPlay() { Super::BeginPlay(); } void ARWTHVRPawn::Tick(float DeltaSeconds) { @@ -56,6 +78,17 @@ void ARWTHVRPawn::Tick(float DeltaSeconds) EvaluateLivelink(); } +/* + * Scales the Pawn while also adjusting the WorldToMeters ratio to adjust for pupillary distance. + * Only supports uniform scaling. + */ +void ARWTHVRPawn::SetScale(float NewScale) +{ + FVector NewScaleVector = FVector(NewScale, NewScale, NewScale); + GetWorldSettings()->WorldToMeters = InitialWorldToMeters * NewScale; + SetActorScale3D(NewScaleVector); +} + /* * The alternative would be to do this only on the server on possess and check for player state/type, * as connections now send their playertype over. @@ -71,7 +104,7 @@ void ARWTHVRPawn::NotifyControllerChanged() if (HasAuthority()) { UE_LOG(Toolkit, Display, - TEXT("ARWTHVRPawn: Player Controller has changed, trying to change Cluster attachment if possible...")); + TEXT("ARWTHVRPawn: Player Controller has changed, trying to change Cluster attachment if possible...")); if (const ARWTHVRPlayerState* State = GetPlayerState<ARWTHVRPlayerState>()) { const EPlayerType Type = State->GetPlayerType(); @@ -101,7 +134,7 @@ void ARWTHVRPawn::SetupPlayerInputComponent(UInputComponent* PlayerInputComponen } UE_LOGFMT(Toolkit, Display, "SetupPlayerInputComponent: Player Controller is valid, setting up input for {Pawn}", - GetName()); + GetName()); // Set the control rotation of the PC to zero again. There is a small period of 2 frames where, when the pawn gets @@ -173,7 +206,7 @@ void ARWTHVRPawn::AddInputMappingContext(const APlayerController* PC, const UInp else { UE_LOGFMT(Toolkit, Warning, - "ARWTHVRPawn::AddInputMappingContext: UEnhancedInputLocalPlayerSubsystem is nullptr!"); + "ARWTHVRPawn::AddInputMappingContext: UEnhancedInputLocalPlayerSubsystem is nullptr!"); } } else @@ -201,7 +234,7 @@ void ARWTHVRPawn::EvaluateLivelink() const IModularFeatures::Get().GetModularFeature<ILiveLinkClient>(ILiveLinkClient::ModularFeatureName); FLiveLinkSubjectFrameData SubjectData; const bool bHasValidData = LiveLinkClient.EvaluateFrame_AnyThread(HeadSubjectRepresentation.Subject, - HeadSubjectRepresentation.Role, SubjectData); + HeadSubjectRepresentation.Role, SubjectData); if (!bHasValidData) { @@ -278,12 +311,12 @@ void ARWTHVRPawn::AttachClustertoPawn() bool bAttached = ClusterActor->AttachToComponent(GetRootComponent(), AttachmentRules); // State->GetCorrespondingClusterActor()->OnAttached(); UE_LOGFMT(Toolkit, Display, - "ARWTHVRPawn: Attaching corresponding cluster actor to our pawn returned: {Attached}", bAttached); + "ARWTHVRPawn: Attaching corresponding cluster actor to our pawn returned: {Attached}", bAttached); } else { UE_LOGFMT(Toolkit, Error, - "ARWTHVRPawn::AttachClustertoPawn: No ARWTHVRPlayerState set! This won't work on the Cave."); + "ARWTHVRPawn::AttachClustertoPawn: No ARWTHVRPlayerState set! This won't work on the Cave."); } if (HasAuthority()) // Should always be the case here, but double check @@ -321,19 +354,19 @@ void ARWTHVRPawn::SetCameraOffset() const } void ARWTHVRPawn::ApplyLiveLinkTransform(const FTransform& Transform, - const FLiveLinkTransformStaticData& StaticData) const + const FLiveLinkTransformStaticData& StaticData) const { if (StaticData.bIsLocationSupported) { if (bWorldTransform) { HeadCameraComponent->SetWorldLocation(Transform.GetLocation(), false, nullptr, - ETeleportType::TeleportPhysics); + ETeleportType::TeleportPhysics); } else { HeadCameraComponent->SetRelativeLocation(Transform.GetLocation(), false, nullptr, - ETeleportType::TeleportPhysics); + ETeleportType::TeleportPhysics); } } @@ -342,12 +375,12 @@ void ARWTHVRPawn::ApplyLiveLinkTransform(const FTransform& Transform, if (bWorldTransform) { HeadCameraComponent->SetWorldRotation(Transform.GetRotation(), false, nullptr, - ETeleportType::TeleportPhysics); + ETeleportType::TeleportPhysics); } else { HeadCameraComponent->SetRelativeRotation(Transform.GetRotation(), false, nullptr, - ETeleportType::TeleportPhysics); + ETeleportType::TeleportPhysics); } } @@ -362,4 +395,4 @@ void ARWTHVRPawn::ApplyLiveLinkTransform(const FTransform& Transform, HeadCameraComponent->SetRelativeScale3D(Transform.GetScale3D()); } } -} +} \ No newline at end of file diff --git a/Source/RWTHVRToolkit/Public/Pawn/RWTHVRPawn.h b/Source/RWTHVRToolkit/Public/Pawn/RWTHVRPawn.h index cd81e497181dcfef757b067ccae8c862c022fa34..eaf24745465f7b78b3a46630db8d324704a55b60 100644 --- a/Source/RWTHVRToolkit/Public/Pawn/RWTHVRPawn.h +++ b/Source/RWTHVRToolkit/Public/Pawn/RWTHVRPawn.h @@ -31,6 +31,9 @@ public: virtual void NotifyControllerChanged() override; + UFUNCTION(BlueprintCallable) + void SetScale(float NewScale); + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Pawn|Input") TArray<UInputMappingContext*> InputMappingContexts; @@ -111,4 +114,5 @@ protected: private: UInputComponent* ActivePlayerInputComponent; + float InitialWorldToMeters; };