diff --git a/Content/Components/Movement/Scale/BP_ScalingComponent.uasset b/Content/Components/Movement/Scale/BP_ScalingComponent.uasset new file mode 100644 index 0000000000000000000000000000000000000000..1eaae41128a98d480b90e3d5f688d0e91568ac4b Binary files /dev/null and b/Content/Components/Movement/Scale/BP_ScalingComponent.uasset differ diff --git a/Content/Components/Movement/Scale/IA_Grow.uasset b/Content/Components/Movement/Scale/IA_Grow.uasset new file mode 100644 index 0000000000000000000000000000000000000000..4fa554d2f3a4358e59810f330ac81f9b1bf5d73a Binary files /dev/null and b/Content/Components/Movement/Scale/IA_Grow.uasset differ diff --git a/Content/Components/Movement/Scale/IA_ResetScale.uasset b/Content/Components/Movement/Scale/IA_ResetScale.uasset new file mode 100644 index 0000000000000000000000000000000000000000..096bc1d4cb496f7df83b9d0aff99d70a3aae13e9 Binary files /dev/null and b/Content/Components/Movement/Scale/IA_ResetScale.uasset differ diff --git a/Content/Components/Movement/Scale/IA_Shrink.uasset b/Content/Components/Movement/Scale/IA_Shrink.uasset new file mode 100644 index 0000000000000000000000000000000000000000..2ef23e85a28e3f50da12c5a84bfa92f1367c2e57 Binary files /dev/null and b/Content/Components/Movement/Scale/IA_Shrink.uasset differ diff --git a/Content/Input/Default_IMC/IMC_MovementLeftHand.uasset b/Content/Input/Default_IMC/IMC_MovementLeftHand.uasset index 3a6f11f161b72dcf7957b8badedca6df9f64ec20..a688bcc47ef30ebaeeb28592df4a0c2c00ee4c68 100644 Binary files a/Content/Input/Default_IMC/IMC_MovementLeftHand.uasset and b/Content/Input/Default_IMC/IMC_MovementLeftHand.uasset differ diff --git a/Content/Input/Default_IMC/IMC_MovementRightHand.uasset b/Content/Input/Default_IMC/IMC_MovementRightHand.uasset index 3aeafce240b599eb78bc9305707d2198bfd53613..aa1f8437dcb5cb367674b6c27fc1a84357dac27a 100644 Binary files a/Content/Input/Default_IMC/IMC_MovementRightHand.uasset and b/Content/Input/Default_IMC/IMC_MovementRightHand.uasset differ diff --git a/Source/RWTHVRToolkit/Private/Pawn/Navigation/HeightTeleportationComponent.cpp b/Source/RWTHVRToolkit/Private/Pawn/Navigation/HeightTeleportationComponent.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5741ec92691e23972948285fdaaf5a639730ee1e --- /dev/null +++ b/Source/RWTHVRToolkit/Private/Pawn/Navigation/HeightTeleportationComponent.cpp @@ -0,0 +1,5 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "Pawn/Navigation/HeightTeleportationComponent.h" + diff --git a/Source/RWTHVRToolkit/Private/Pawn/Navigation/ScalingComponent.cpp b/Source/RWTHVRToolkit/Private/Pawn/Navigation/ScalingComponent.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b5ce41191503c545a4856476ed59f808e28aff79 --- /dev/null +++ b/Source/RWTHVRToolkit/Private/Pawn/Navigation/ScalingComponent.cpp @@ -0,0 +1,276 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "Pawn/Navigation/ScalingComponent.h" + +#include "EnhancedInputComponent.h" +#include "HeadMountedDisplayFunctionLibrary.h" +#include "MotionControllerComponent.h" +#include "EntitySystem/MovieSceneComponentDebug.h" +#include "Pawn/RWTHVRPawn.h" +#include "Utility/RWTHVRUtilities.h" + + + +void UScalingComponent::BeginPlay() +{ + Super::BeginPlay(); + + MotionController = VRPawn->RightHand; + + ScalingDelegate.AddDynamic(this, &UScalingComponent::AdjustFeedbackMesh); + + FloatingPawnMovement = Cast<UFloatingPawnMovement>(VRPawn->GetMovementComponent()); + if(!FloatingPawnMovement) + { + UE_LOG(Toolkit,Error,TEXT("[ScalingComponent]: Cannot find FloatingPawnMovement at VRPawn")) + } + + DefaultAcceleration = FloatingPawnMovement->Acceleration; + DefaultDeceleration = FloatingPawnMovement->Deceleration; + DefaultMaxSpeed = FloatingPawnMovement->MaxSpeed; + + // Spawn the feedback meshes that indicate the current size in relation to the original size + FActorSpawnParameters Params; + + OriginalSizeMesh = GetWorld()->SpawnActor<AStaticMeshActor>(Params); + OriginalSizeMesh->GetStaticMeshComponent()->Mobility = EComponentMobility::Movable; + OriginalSizeMesh->SetMobility(EComponentMobility::Movable); + FVector LocationAboveController = MotionController->GetComponentLocation(); + LocationAboveController += MotionController->GetUpVector() * 10; + LocationAboveController += MotionController->GetForwardVector() * 15; + LocationAboveController += MotionController->GetRightVector() * FeedbackMeshDistance / 2.f; + OriginalSizeMesh->SetActorLocation(LocationAboveController); + + + OriginalSizeMesh->GetStaticMeshComponent()->SetStaticMesh(FeedbackMesh); + OriginalSizeMesh->SetActorScale3D(FVector(0.1, 0.1, 0.1)); + + OriginalSizeMesh->GetStaticMeshComponent()->AttachToComponent(MotionController, + FAttachmentTransformRules( + EAttachmentRule::KeepWorld, + EAttachmentRule::KeepRelative, + EAttachmentRule::KeepRelative, false)); + + CurrentSizeMesh = GetWorld()->SpawnActor<AStaticMeshActor>(Params); + CurrentSizeMesh->GetStaticMeshComponent()->Mobility = EComponentMobility::Movable; + CurrentSizeMesh->SetMobility(EComponentMobility::Movable); + LocationAboveController = MotionController->GetComponentLocation(); + LocationAboveController += MotionController->GetUpVector() * 10; + LocationAboveController += MotionController->GetForwardVector() * 15; + LocationAboveController -= MotionController->GetRightVector() * FeedbackMeshDistance / 2.f; + CurrentSizeMesh->SetActorLocation(LocationAboveController); + + + CurrentSizeMesh->GetStaticMeshComponent()->SetStaticMesh(FeedbackMesh); + CurrentSizeMesh->SetActorScale3D(FVector(0.1, 0.1, 0.1)); + + CurrentSizeMesh->GetStaticMeshComponent()->AttachToComponent(MotionController, + FAttachmentTransformRules( + EAttachmentRule::KeepWorld, + EAttachmentRule::KeepRelative, + EAttachmentRule::KeepWorld, false)); + + // Disable collisions of preview meshes + OriginalSizeMesh->SetActorEnableCollision(false); + CurrentSizeMesh->SetActorEnableCollision(false); + + // Correct rotation of meshes + FRotator Corrector = FRotator(0, 90, 0); + OriginalSizeMesh->AddActorLocalRotation(Corrector); + CurrentSizeMesh->AddActorLocalRotation(Corrector); + + // Add controllers as equal sized components so thei scale accordingly + + AddEqualSizedComponent(VRPawn->LeftHand); + AddEqualSizedComponent(VRPawn->RightHand); + +} + +void UScalingComponent::SetupPlayerInput(UInputComponent* PlayerInputComponent) +{ + Super::SetupPlayerInput(PlayerInputComponent); + + + if (!VRPawn || !VRPawn->HasLocalNetOwner()) + { + return; + } + + UEnhancedInputComponent* EI = Cast<UEnhancedInputComponent>(PlayerInputComponent); + if (!EI) + { + UE_LOG(Toolkit, Error, TEXT("Cannot cast Input Component to Enhanced Input Component in ScalingComponent")); + return; + } + + // teleporting + EI->BindAction(Grow, ETriggerEvent::Completed, this, &UScalingComponent::OnGrow); + EI->BindAction(Shrink, ETriggerEvent::Completed, this, &UScalingComponent::OnShrink); + EI->BindAction(ResetScale, ETriggerEvent::Completed, this, &UScalingComponent::OnResetScale); + // turning is defined in MovementComponentBase +} + +void UScalingComponent::OnGrow(const FInputActionValue& InputActionValue) +{ + float CurrentW2MScale = UHeadMountedDisplayFunctionLibrary::GetWorldToMetersScale(GetOwner()->GetWorld()); + float PreviousScale = CurrentW2MScale; // store for computing scale ratio + + CurrentW2MScale = CurrentW2MScale * (1 + ScaleStepSize); + GNearClippingPlane = CurrentW2MScale; + + FloatingPawnMovement->Acceleration = DefaultAcceleration * CurrentW2MScale/100; + FloatingPawnMovement->Deceleration = DefaultDeceleration* CurrentW2MScale/100; + FloatingPawnMovement->MaxSpeed = DefaultMaxSpeed * CurrentW2MScale/100; + + if (CurrentW2MScale > MaxScale || CurrentW2MScale < MinScale) + { + UE_LOG(LogTemp, Warning, TEXT("Exceeding scale limits!")); + return; + } + + CurrentW2MScale = FMath::Clamp(CurrentW2MScale, MinScale, MaxScale); + // min and max are swapped here due to the inverse nature of the WorldToMeterScale attribute + float ScaleRatio = CurrentW2MScale / PreviousScale; + + AdjustEqualSizedWorldObjects(ScaleRatio); + UHeadMountedDisplayFunctionLibrary::SetWorldToMetersScale(GetOwner()->GetWorld(), CurrentW2MScale); + // inform all subscribed actors of the scale change + ScalingDelegate.Broadcast(ScaleRatio, false, VRPawn->GetActorLocation()); + + //DrawDebugSphere(GetWorld(), ParentActor->GetActorLocation(), 15, 15, FColor::Red, false, 10); +} + +void UScalingComponent::OnShrink(const FInputActionValue& InputActionValue) +{ + float CurrentW2MScale = UHeadMountedDisplayFunctionLibrary::GetWorldToMetersScale(GetOwner()->GetWorld()); + float PreviousScale = CurrentW2MScale; // store for computing scale ratio + CurrentW2MScale = CurrentW2MScale / (1.f + ScaleStepSize); + + GNearClippingPlane = CurrentW2MScale; + FloatingPawnMovement->Acceleration = DefaultAcceleration * CurrentW2MScale/100; + FloatingPawnMovement->Deceleration = DefaultDeceleration * CurrentW2MScale/100; + FloatingPawnMovement->MaxSpeed = DefaultMaxSpeed * CurrentW2MScale/100; + + if (CurrentW2MScale > MaxScale || CurrentW2MScale < MinScale) + { + UE_LOG(LogTemp, Warning, TEXT("Exceeding scale limits!")); + return; + } + + CurrentW2MScale = FMath::Clamp(CurrentW2MScale, MinScale, MaxScale); + // min and max are swapped here due to the inverse nature of the WorldToMeterScale attribute + float ScaleRatio = CurrentW2MScale / PreviousScale; + + AdjustEqualSizedWorldObjects(ScaleRatio); + UHeadMountedDisplayFunctionLibrary::SetWorldToMetersScale(GetOwner()->GetWorld(), CurrentW2MScale); + // inform all subscribed actors of the scale change + ScalingDelegate.Broadcast(ScaleRatio, false, VRPawn->GetActorLocation()); + + + //DrawDebugSphere(GetWorld(), ParentActor->GetActorLocation(), 15, 15, FColor::Red, true, 10); +} + +void UScalingComponent::OnResetScale(const FInputActionValue& InputActionValue) +{ + UE_LOG(LogTemp, Error, TEXT("Resetting Scale")); + + float CurrentW2MScale = UHeadMountedDisplayFunctionLibrary::GetWorldToMetersScale(GetOwner()->GetWorld()); + float PreviousScale = CurrentW2MScale; // store for computing scale ratio + CurrentW2MScale = OriginalScale; + GNearClippingPlane = CurrentW2MScale; + + FloatingPawnMovement->Acceleration = DefaultAcceleration * CurrentW2MScale/100; + FloatingPawnMovement->Deceleration = DefaultDeceleration * CurrentW2MScale/100; + FloatingPawnMovement->MaxSpeed = DefaultMaxSpeed * CurrentW2MScale/100; + + CurrentW2MScale = FMath::Clamp(CurrentW2MScale, MinScale, MaxScale); + // min and max are swapped here due to the inverse nature of the WorldToMeterScale attribute + float ScaleRatio = CurrentW2MScale / PreviousScale; + + AdjustEqualSizedWorldObjects(ScaleRatio); + UHeadMountedDisplayFunctionLibrary::SetWorldToMetersScale(GetOwner()->GetWorld(), CurrentW2MScale); + + // Scale the visualizer + + //CurrentSizeMesh->SetActorScale3D(FVector(0.1,0.1,0.1)); + + // inform all subscribed actors of the scale change + ScalingDelegate.Broadcast(ScaleRatio, true, VRPawn->GetActorLocation()); + //ScalingResetDelegate.Broadcast(); +} + +float UScalingComponent::GetTotalScaleRatio() +{ + return OriginalScale / UHeadMountedDisplayFunctionLibrary::GetWorldToMetersScale(GetOwner()->GetWorld()); +} + +void UScalingComponent::AddEqualSizedActor(AActor* ActorToKeepEqual) +{ + if (ActorToKeepEqual != nullptr) + { + EqualSizedActors.AddUnique(ActorToKeepEqual); + } + else + { + UE_LOG(LogTemp, Fatal, TEXT("No valid actor was passed to method AddEqualSizedActor()!")); + } +} + +void UScalingComponent::AddEqualSizedComponent(USceneComponent* SceneComponentToKeepEqual) +{ + if (SceneComponentToKeepEqual != nullptr) + { + EqualSizedSceneComponents.AddUnique(SceneComponentToKeepEqual); + } + else + { + UE_LOG(LogTemp, Fatal, TEXT("No valid USceneComponent was passed to method AddEqualSizedComponent() !")); + } +} + +void UScalingComponent::AdjustEqualSizedWorldObjects(float ScaleRatio) +{ + // adjust actors + for (AActor* CurrActor : EqualSizedActors) + { + //UE_LOG(LogTemp, Warning, TEXT("Scaling Actor")); + FVector CurrentScaling = CurrActor->GetActorScale3D(); + CurrActor->SetActorScale3D(CurrentScaling * ScaleRatio); + } + + // adjust scene components + for (USceneComponent* CurrComponent : EqualSizedSceneComponents) + { + //UE_LOG(LogTemp, Warning, TEXT("Scaling Component")); + FVector CurrentScaling = CurrComponent->GetComponentScale(); + CurrComponent->SetWorldScale3D(CurrentScaling * ScaleRatio); + } +} + +void UScalingComponent::AdjustFeedbackMesh(float NewWMSRation, bool isReset, FVector NewPos) +{ + TotalScaleRatio *= NewWMSRation; + + FVector Scale = CurrentSizeMesh->GetActorScale3D(); + Scale *= NewWMSRation; + CurrentSizeMesh->SetActorScale3D(Scale); + + ControllerUpOffset *= NewWMSRation; + ControllerForwardOffset *= NewWMSRation; + FeedbackMeshDistance *= NewWMSRation; + + FVector LocationAboveController = MotionController->GetComponentLocation(); + LocationAboveController += + MotionController->GetUpVector() * ControllerUpOffset; + LocationAboveController += + MotionController->GetForwardVector() * ControllerForwardOffset; + LocationAboveController += + MotionController->GetRightVector() * FeedbackMeshDistance / 2.f; + OriginalSizeMesh->SetActorLocation(LocationAboveController); + + LocationAboveController -= + MotionController->GetRightVector() * FeedbackMeshDistance; + CurrentSizeMesh->SetActorLocation(LocationAboveController); +} + diff --git a/Source/RWTHVRToolkit/Public/Pawn/Navigation/HeightTeleportationComponent.h b/Source/RWTHVRToolkit/Public/Pawn/Navigation/HeightTeleportationComponent.h new file mode 100644 index 0000000000000000000000000000000000000000..cfe567426000d08aee1c45d94f6714c7bbc4750b --- /dev/null +++ b/Source/RWTHVRToolkit/Public/Pawn/Navigation/HeightTeleportationComponent.h @@ -0,0 +1,19 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "Pawn/Navigation/MovementComponentBase.h" +#include "HeightTeleportationComponent.generated.h" + +/** + * + */ +UCLASS() +class RWTHVRTOOLKIT_API UHeightTeleportationComponent : public UMovementComponentBase +{ + GENERATED_BODY() + + // Spawn the TwoStepHandler etc. (Basically what was done in the VRPawn directly) + +}; diff --git a/Source/RWTHVRToolkit/Public/Pawn/Navigation/ScalingComponent.h b/Source/RWTHVRToolkit/Public/Pawn/Navigation/ScalingComponent.h new file mode 100644 index 0000000000000000000000000000000000000000..39f26c9c1f4b4af1fdb8e362780a42a73a0b190c --- /dev/null +++ b/Source/RWTHVRToolkit/Public/Pawn/Navigation/ScalingComponent.h @@ -0,0 +1,155 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "InputActionValue.h" +#include "Engine/StaticMeshActor.h" +#include "GameFramework/FloatingPawnMovement.h" +#include "GameFramework/MovementComponent.h" +#include "Pawn/Navigation/MovementComponentBase.h" +#include "ScalingComponent.generated.h" + +/** + * + */ +UCLASS(Blueprintable) +class RWTHVRTOOLKIT_API UScalingComponent : public UMovementComponentBase +{ + GENERATED_BODY() + +public: + virtual void SetupPlayerInput(UInputComponent* PlayerInputComponent) override; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VR Movement") + bool bMoveWithRightHand = true; + + UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "VR Movement|Input|Actions") + UInputAction* Grow; + + UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "VR Movement|Input|Actions") + UInputAction* Shrink; + + UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "VR Movement|Input|Actions") + UInputAction* ResetScale; + + UFUNCTION(BlueprintCallable) + void OnGrow(const FInputActionValue& InputActionValue); + UFUNCTION(BlueprintCallable) + void OnShrink(const FInputActionValue& InputActionValue); + UFUNCTION(BlueprintCallable) + void OnResetScale(const FInputActionValue& InputActionValue); + + + + // code from marius: + UFUNCTION(BlueprintCallable) + void SetMaxScale(float UpperLimit) + { + MaxScale = UpperLimit; + } + + UFUNCTION(BlueprintCallable) + void SetMinScale(float LowerLimit) + { + MinScale = LowerLimit; + } + + UFUNCTION(BlueprintCallable) + void SetStepSize(float StepSize) + { + ScaleStepSize = StepSize; + } + + UFUNCTION(BlueprintCallable) + float GetStepSize() + { + return ScaleStepSize; + } + + float GetTotalScaleRatio(); + + + UFUNCTION(BlueprintCallable) + void AddEqualSizedActor(AActor* ActorToKeepEqual); + + UFUNCTION(BlueprintCallable) + void AddEqualSizedComponent(USceneComponent* SceneComponentToKeepEqual); + + void AdjustEqualSizedWorldObjects(float ScaleRatio); + + UFUNCTION() + void AdjustFeedbackMesh(float NewWMSRation, bool isReset = true, FVector NewPos = FVector::Zero()); + + void SetFeedbackMesh(UStaticMesh* NewMesh) + { + FeedbackMesh = NewMesh; + OriginalSizeMesh->GetStaticMeshComponent()->SetStaticMesh(FeedbackMesh); + CurrentSizeMesh->GetStaticMeshComponent()->SetStaticMesh(FeedbackMesh); + } + + // Scaling Delegate that other actors can subscribe to + DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FScalingDelegate, float, NewWorldScaling, bool, isReset, FVector, + AdjustedPawnLocation); + + UPROPERTY(BlueprintAssignable) + FScalingDelegate ScalingDelegate; + + DECLARE_DYNAMIC_MULTICAST_DELEGATE(FScalingResetDelegate); + + UPROPERTY(BlueprintAssignable) + FScalingResetDelegate ScalingResetDelegate; + + UPROPERTY(EditAnywhere) + UMotionControllerComponent* MotionController = nullptr; + + UPROPERTY(EditAnywhere) + TArray<AActor*> EqualSizedActors; + + UPROPERTY(EditAnywhere) + TArray<USceneComponent*> EqualSizedSceneComponents; + + + //Boundaries of Scaling (inverse relation: Increasing the WorldToMeterScale decreases the pawns size (as the world increases)) + UPROPERTY(EditAnywhere) + float MinScale = 10; + + UPROPERTY(EditAnywhere) + float MaxScale = 350; + + UPROPERTY(EditAnywhere) + float ScaleStepSize = 0.2; +protected: + + // Called when the game starts + virtual void BeginPlay() override; + + +private: + + UPROPERTY() + float OriginalScale = 100; + + float TotalScaleRatio = 1; + + // Components For Visual Feedback + UPROPERTY(EditAnywhere) + UStaticMesh* FeedbackMesh = nullptr; + UPROPERTY(EditAnywhere) + AStaticMeshActor* OriginalSizeMesh = nullptr; + UPROPERTY(EditAnywhere) + AStaticMeshActor* CurrentSizeMesh = nullptr; + float FeedbackMeshDistance = 15; + float ControllerForwardOffset = 15; + float ControllerUpOffset = 10; + + // boolean for scaling behaviour + bool bHasScaled = false; + + UFloatingPawnMovement* FloatingPawnMovement; + float DefaultAcceleration; + float DefaultDeceleration; + float DefaultMaxSpeed; +}; + + diff --git a/Source/RWTHVRToolkit/Public/Pawn/Navigation/TeleportationComponent.h b/Source/RWTHVRToolkit/Public/Pawn/Navigation/TeleportationComponent.h index 308634643f4a0ad6520ab882e384a8bbe8ff8e96..04fbe704c81473e540c2ad000fbab35f11a1f2b0 100644 --- a/Source/RWTHVRToolkit/Public/Pawn/Navigation/TeleportationComponent.h +++ b/Source/RWTHVRToolkit/Public/Pawn/Navigation/TeleportationComponent.h @@ -60,6 +60,8 @@ public: virtual void SetupPlayerInput(UInputComponent* PlayerInputComponent) override; + UPROPERTY(BlueprintReadOnly) + AActor* TeleportVisualizer; private: UPROPERTY() UMotionControllerComponent* TeleportationHand; @@ -73,7 +75,5 @@ private: FPredictProjectilePathResult PredictResult; bool bValidTeleportLocation = false; FVector FinalTeleportLocation; - - UPROPERTY() - AActor* TeleportVisualizer; + }; diff --git a/Source/RWTHVRToolkit/RWTHVRToolkit.Build.cs b/Source/RWTHVRToolkit/RWTHVRToolkit.Build.cs index 930dc9129b0fbcf2ba9b275595cea42f42866238..6eb5214453bce561b46287afced08e1ff452cabb 100644 --- a/Source/RWTHVRToolkit/RWTHVRToolkit.Build.cs +++ b/Source/RWTHVRToolkit/RWTHVRToolkit.Build.cs @@ -38,7 +38,7 @@ public class RWTHVRToolkit : ModuleRules PrivateDependencyModuleNames.AddRange( new string[] { - "NetCore" + "NetCore", "XRBase", "XRBase" } ); if (Target.bBuildEditor == true)