diff --git a/Source/StevesUEHelpers/Private/StevesSpringArmComponent.cpp b/Source/StevesUEHelpers/Private/StevesSpringArmComponent.cpp new file mode 100644 index 0000000..0af87f8 --- /dev/null +++ b/Source/StevesUEHelpers/Private/StevesSpringArmComponent.cpp @@ -0,0 +1,41 @@ + +#include "StevesSpringArmComponent.h" + + +UStevesSpringArmComponent::UStevesSpringArmComponent() +{ + +} + +FVector UStevesSpringArmComponent::BlendLocations(const FVector& DesiredArmLocation, + const FVector& TraceHitLocation, + bool bHitSomething, + float DeltaTime) +{ + // These locations are in world space, we only want to blend the arm length, not the rest + const FVector Base = Super::BlendLocations(DesiredArmLocation, TraceHitLocation, bHitSomething, DeltaTime); + + if (bEnableSmoothCollisionAvoidance) + { + // Convert these back to arm lengths + // PreviousArmOrigin has been already set and is the world space origin + const float TargetArmLen = (Base - PreviousArmOrigin).Length(); + + const float NewArmLen = FMath::FInterpTo(PrevArmLength.Get(TargetArmLen), TargetArmLen, DeltaTime, SmoothCollisionAvoidanceSpeed); + + // Perform the same transformation again using the new arm length + // Now offset camera position back along our rotation + FVector Ret = PreviousDesiredLoc - PreviousDesiredRot.Vector() * NewArmLen; + // Add socket offset in local space + Ret += FRotationMatrix(PreviousDesiredRot).TransformVector(SocketOffset); + + PrevArmLength = NewArmLen; + + return Ret; + } + else + { + return Base; + } + +} diff --git a/Source/StevesUEHelpers/Public/StevesSpringArmComponent.h b/Source/StevesUEHelpers/Public/StevesSpringArmComponent.h new file mode 100644 index 0000000..32c43cc --- /dev/null +++ b/Source/StevesUEHelpers/Public/StevesSpringArmComponent.h @@ -0,0 +1,34 @@ + +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/SpringArmComponent.h" +#include "StevesSpringArmComponent.generated.h" + + +UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent)) +class STEVESUEHELPERS_API UStevesSpringArmComponent : public USpringArmComponent +{ + GENERATED_BODY() +public: + /// Whether to move the camera smoothly to avoid collisions rather than jumping instantly + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=CameraCollision) + uint32 bEnableSmoothCollisionAvoidance : 1 = true; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=CameraCollision) + float SmoothCollisionAvoidanceSpeed = 5; + +protected: + TOptional PrevArmLength; + + +public: + UStevesSpringArmComponent(); + +protected: + virtual FVector BlendLocations(const FVector& DesiredArmLocation, + const FVector& TraceHitLocation, + bool bHitSomething, + float DeltaTime) override; +}; +