Files
ProjectEleri/Plugins/StevesUEHelpers/Source/StevesUEHelpers/Private/StevesSpringArmComponent.cpp

117 lines
3.9 KiB
C++

// Copyright Steve Streeting 2020 onwards
// Released under the MIT license
#include "StevesSpringArmComponent.h"
#include "VisualLogger/VisualLogger.h"
#include "StevesUEHelpers.h"
UStevesSpringArmComponent::UStevesSpringArmComponent(): bEnableSmoothCollisionAvoidance(1)
{
}
void UStevesSpringArmComponent::UpdateDesiredArmLocation(bool bDoTrace,
bool bDoLocationLag,
bool bDoRotationLag,
float DeltaTime)
{
// Smooth target & socket offsets
if (SmoothTargetOffsetTarget.IsSet())
{
TargetOffset = FMath::VInterpTo(TargetOffset, SmoothTargetOffsetTarget.GetValue(), DeltaTime, SmoothTargetOffsetSpeed);
if (TargetOffset.Equals(SmoothTargetOffsetTarget.GetValue()))
{
CancelTargetOffsetSmooth();
}
}
if (SmoothSocketOffsetTarget.IsSet())
{
SocketOffset = FMath::VInterpTo(SocketOffset, SmoothSocketOffsetTarget.GetValue(), DeltaTime, SmoothSocketOffsetSpeed);
if (SocketOffset.Equals(SmoothSocketOffsetTarget.GetValue()))
{
CancelSocketOffsetSmooth();
}
}
Super::UpdateDesiredArmLocation(bDoTrace, bDoLocationLag, bDoRotationLag, DeltaTime);
}
FVector UStevesSpringArmComponent::BlendLocations(const FVector& DesiredArmLocation,
const FVector& TraceHitLocation,
bool bHitSomething,
float DeltaTime)
{
#if WITH_EDITORONLY_DATA && ENABLE_VISUAL_LOG
if (bHitSomething && bVisualLogCameraCollision)
{
FVector NewDesiredLoc = PreviousDesiredLoc - PreviousDesiredRot.Vector() * TargetArmLength;
// Add socket offset in local space
NewDesiredLoc += FRotationMatrix(PreviousDesiredRot).TransformVector(SocketOffset);
FCollisionQueryParams QueryParams(SCENE_QUERY_STAT(SpringArm), false, GetOwner());
FHitResult Result;
if (GetWorld()->SweepSingleByChannel(Result, PreviousArmOrigin, NewDesiredLoc, FQuat::Identity, ProbeChannel, FCollisionShape::MakeSphere(ProbeSize), QueryParams))
{
UE_VLOG_ARROW(this, LogStevesUEHelpers, Log, PreviousArmOrigin, Result.Location, FColor::Cyan, TEXT(""));
UE_VLOG_LOCATION(this, LogStevesUEHelpers, Log, Result.Location, ProbeSize, FColor::Cyan, TEXT("%s"), *Result.GetActor()->GetActorNameOrLabel());
}
}
#endif
// 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;
}
}
void UStevesSpringArmComponent::SetTargetOffsetSmooth(const FVector& NewTargetOffset, float Speed)
{
SmoothTargetOffsetTarget = NewTargetOffset;
SmoothTargetOffsetSpeed = Speed;
}
void UStevesSpringArmComponent::CancelTargetOffsetSmooth()
{
SmoothTargetOffsetTarget.Reset();
}
void UStevesSpringArmComponent::SetSocketOffsetSmooth(const FVector& NewSocketOffset, float Speed)
{
SmoothSocketOffsetTarget = NewSocketOffset;
SmoothSocketOffsetSpeed = Speed;
}
void UStevesSpringArmComponent::CancelSocketOffsetSmooth()
{
SmoothSocketOffsetTarget.Reset();
}
void UStevesSpringArmComponent::JumpToDesiredLocation()
{
CancelTargetOffsetSmooth();
CancelSocketOffsetSmooth();
UpdateDesiredArmLocation(false, false, false, 0);
}