250 lines
8.3 KiB
C++
250 lines
8.3 KiB
C++
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
|
|
|
|
#include "Collision/GCS_TraceStructLibrary.h"
|
|
|
|
#include "GCS_LogChannels.h"
|
|
#include "Components/BoxComponent.h"
|
|
#include "Components/CapsuleComponent.h"
|
|
#include "Components/SphereComponent.h"
|
|
#include "TargetingSystem/TargetingPreset.h"
|
|
|
|
|
|
bool FGCS_CollisionShape::InitializeShape(const UPrimitiveComponent* SourceComponent)
|
|
{
|
|
GCS_OWNED_CLOG(SourceComponent, Warning, "Should never use this shape:%s", *FGCS_CollisionShape::StaticStruct()->GetName());
|
|
FDebug::DumpStackTraceToLog(ELogVerbosity::VeryVerbose);
|
|
return false;
|
|
}
|
|
|
|
FTransform FGCS_CollisionShape::GetTransform(const UPrimitiveComponent* SourceComponent, const float& Time) const
|
|
{
|
|
GCS_OWNED_CLOG(SourceComponent, Warning, "Should never use this shape:%s", *FGCS_CollisionShape::StaticStruct()->GetName());
|
|
FDebug::DumpStackTraceToLog(ELogVerbosity::VeryVerbose);
|
|
return SourceComponent->GetComponentTransform();
|
|
}
|
|
|
|
FCollisionShape FGCS_CollisionShape::GetDynamicCollisionShape(const UPrimitiveComponent* SourceComponent, const float& Time) const
|
|
{
|
|
GCS_OWNED_CLOG(SourceComponent, Warning, "Should never use this shape:%s", *FGCS_CollisionShape::StaticStruct()->GetName());
|
|
FDebug::DumpStackTraceToLog(ELogVerbosity::VeryVerbose);
|
|
return FCollisionShape::MakeSphere(30);
|
|
}
|
|
|
|
bool FGCS_CollisionShape_Static::InitializeShape(const UPrimitiveComponent* SourceComponent)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
FTransform FGCS_CollisionShape_Static::GetTransform(const UPrimitiveComponent* SourceComponent, const float& Time) const
|
|
{
|
|
const auto ComponentCurrentTransform = SourceComponent->GetComponentTransform();
|
|
return FTransform(Orientation, Offset) * ComponentCurrentTransform;
|
|
}
|
|
|
|
FCollisionShape FGCS_CollisionShape_Static::GetDynamicCollisionShape(const UPrimitiveComponent* SourceComponent, const float& Time) const
|
|
{
|
|
switch (ShapeType)
|
|
{
|
|
case EGCS_CollisionShapeType::Sphere:
|
|
{
|
|
return FCollisionShape::MakeSphere(Radius);
|
|
}
|
|
case EGCS_CollisionShapeType::Box:
|
|
{
|
|
return FCollisionShape::MakeBox(HalfSize);
|
|
}
|
|
case EGCS_CollisionShapeType::Capsule:
|
|
{
|
|
return FCollisionShape::MakeCapsule(Radius, HalfHeight);
|
|
}
|
|
default:
|
|
{
|
|
return FCollisionShape::MakeSphere(Radius);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool FGCS_CollisionShape_ShapeBased::InitializeShape(const UPrimitiveComponent* SourceComponent)
|
|
{
|
|
if (ShapeType == EGCS_CollisionShapeType::Sphere)
|
|
{
|
|
if (const auto SphereCollision = Cast<USphereComponent>(SourceComponent))
|
|
{
|
|
Radius = SphereCollision->GetScaledSphereRadius();
|
|
return true;
|
|
}
|
|
GCS_OWNED_CLOG(SourceComponent->GetOwner(), Warning, "No compatible shape component was found! Requires SphereComponent, Got %s(%s)", *GetNameSafe(SourceComponent),
|
|
*SourceComponent->GetClass()->GetName())
|
|
}
|
|
if (ShapeType == EGCS_CollisionShapeType::Box)
|
|
{
|
|
if (const auto BoxCollision = Cast<UBoxComponent>(SourceComponent))
|
|
{
|
|
HalfSize = BoxCollision->GetScaledBoxExtent();
|
|
return true;
|
|
}
|
|
GCS_OWNED_CLOG(SourceComponent->GetOwner(), Warning, "No compatible shape component was found! Requires BoxComponent, Got %s(%s)", *GetNameSafe(SourceComponent),
|
|
*SourceComponent->GetClass()->GetName())
|
|
}
|
|
if (ShapeType == EGCS_CollisionShapeType::Capsule)
|
|
{
|
|
if (const auto CapsuleCollision = Cast<UCapsuleComponent>(SourceComponent))
|
|
{
|
|
HalfHeight = CapsuleCollision->GetScaledCapsuleHalfHeight();
|
|
Radius = CapsuleCollision->GetScaledCapsuleRadius();
|
|
return true;
|
|
}
|
|
GCS_OWNED_CLOG(SourceComponent->GetOwner(), Warning, "No compatible shape component was found! Requires CapsuleComponent, Got %s(%s)", *GetNameSafe(SourceComponent),
|
|
*SourceComponent->GetClass()->GetName())
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
FTransform FGCS_CollisionShape_ShapeBased::GetTransform(const UPrimitiveComponent* SourceComponent, const float& Time) const
|
|
{
|
|
const auto ComponentCurrentTransform = SourceComponent->GetComponentTransform();
|
|
return FTransform(Orientation, Offset) * ComponentCurrentTransform;
|
|
}
|
|
|
|
FCollisionShape FGCS_CollisionShape_ShapeBased::GetDynamicCollisionShape(const UPrimitiveComponent* SourceComponent, const float& Time) const
|
|
{
|
|
switch (ShapeType)
|
|
{
|
|
case EGCS_CollisionShapeType::Sphere:
|
|
{
|
|
return FCollisionShape::MakeSphere(Radius);
|
|
}
|
|
case EGCS_CollisionShapeType::Box:
|
|
{
|
|
return FCollisionShape::MakeBox(HalfSize);
|
|
}
|
|
case EGCS_CollisionShapeType::Capsule:
|
|
{
|
|
return FCollisionShape::MakeCapsule(Radius, HalfHeight);
|
|
}
|
|
default:
|
|
{
|
|
return FCollisionShape::MakeSphere(Radius);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool FGCS_CollisionShape_Attached::InitializeShape(const UPrimitiveComponent* SourceComponent)
|
|
{
|
|
if (!IsValid(SourceComponent) || !SourceComponent->DoesSocketExist(SocketOrBoneName))
|
|
{
|
|
GCS_OWNED_CLOG(SourceComponent->GetOwner(), Warning, "No SocketOrBone(%s) exists on mesh component! Got %s(%s)", *SocketOrBoneName.ToString(), *GetNameSafe(SourceComponent),
|
|
*SourceComponent->GetClass()->GetName())
|
|
FDebug::DumpStackTraceToLog(ELogVerbosity::VeryVerbose);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
FTransform FGCS_CollisionShape_Attached::GetTransform(const UPrimitiveComponent* SourceComponent, const float& Time) const
|
|
{
|
|
const auto BoneTransform = SourceComponent->GetSocketTransform(SocketOrBoneName);
|
|
return FTransform(Orientation, Offset) * BoneTransform;
|
|
}
|
|
|
|
FTransform FGCS_CollisionShape_SocketBased::GetTransform(const UPrimitiveComponent* SourceComponent, const float& Time) const
|
|
{
|
|
const auto ComponentCurrentTransform = SourceComponent->GetComponentTransform();
|
|
return FTransform(Orientation, Offset) * ComponentCurrentTransform;
|
|
}
|
|
|
|
bool FGCS_CollisionShape_SocketBased::InitializeShape(const UPrimitiveComponent* SourceComponent)
|
|
{
|
|
if (const UMeshComponent* MeshComponent = Cast<UMeshComponent>(SourceComponent))
|
|
{
|
|
const auto SocketStartTransform = MeshComponent->GetSocketTransform(MeshSocketStart, RTS_Component);
|
|
const auto SocketStartLocation = SocketStartTransform.GetLocation();
|
|
|
|
const auto SocketEndTransform = MeshComponent->GetSocketTransform(MeshSocketEnd, RTS_Component);
|
|
const auto SocketEndLocation = SocketEndTransform.GetLocation();
|
|
|
|
const FVector CenterLocation = (SocketStartLocation + SocketEndLocation) / 2.f;
|
|
|
|
HalfHeight = FMath::Max((SocketStartLocation - SocketEndLocation).Length() / 2.f + MeshSocketLengthOffset, 1.f);
|
|
Offset = CenterLocation;
|
|
Orientation = FRotationMatrix::MakeFromZ(SocketStartLocation - SocketEndLocation).Rotator();
|
|
|
|
return true;
|
|
}
|
|
GCS_OWNED_CLOG(SourceComponent->GetOwner(), Warning, "No compatible mesh component was found! Got %s(%s)", *GetNameSafe(SourceComponent),
|
|
*SourceComponent->GetClass()->GetName())
|
|
return false;
|
|
}
|
|
|
|
FCollisionShape FGCS_CollisionShape_SocketBased::GetDynamicCollisionShape(const UPrimitiveComponent* SourceComponent, const float& Time) const
|
|
{
|
|
return FCollisionShape::MakeCapsule(Radius, HalfHeight);
|
|
}
|
|
|
|
FGCS_TraceDefinition::FGCS_TraceDefinition()
|
|
{
|
|
CollisionShape.InitializeAs(FGCS_CollisionShape_Static::StaticStruct());
|
|
}
|
|
|
|
bool FGCS_TraceDefinition::IsValidDefinition() const
|
|
{
|
|
// Base collision shape is not allowed!
|
|
return TraceTag.IsValid() && CollisionShape.IsValid() && CollisionShape.GetScriptStruct() != FGCS_CollisionShape::StaticStruct();
|
|
}
|
|
|
|
FString FGCS_TraceDefinition::ToString() const
|
|
{
|
|
return FString::Format(TEXT("{0} {1}"), {TraceTag.ToString(), GetNameSafe(CollisionShape.GetScriptStruct())});
|
|
}
|
|
|
|
bool FGCS_TraceHandle::IsValidHandle() const
|
|
{
|
|
return TraceTag.IsValid() && Guid.IsValid() && SourceObject.IsValid();
|
|
}
|
|
|
|
void FGCS_TraceState::ChangeExecutionState(const bool bNewTraceState, const bool bStopImmediate)
|
|
{
|
|
if (bNewTraceState)
|
|
{
|
|
this->ExecutionState = EGCS_TraceExecutionState::InProgress;
|
|
this->TimeSinceLastTick = 0;
|
|
this->TimeSinceActive = 0;
|
|
this->TotalTickNumDuringExecution = 0;
|
|
this->HitActors.Reset();
|
|
if (SourceComponent)
|
|
{
|
|
UpdatePreviousTransform(GetCurrentTransform());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (this->ExecutionState == EGCS_TraceExecutionState::InProgress && !bStopImmediate)
|
|
{
|
|
this->ExecutionState = EGCS_TraceExecutionState::PendingStop;
|
|
}
|
|
else
|
|
{
|
|
this->ExecutionState = EGCS_TraceExecutionState::Stopped;
|
|
}
|
|
}
|
|
}
|
|
|
|
FTransform FGCS_TraceState::GetCurrentTransform() const
|
|
{
|
|
check(Shape.IsValid())
|
|
return Shape.Get<FGCS_CollisionShape>().GetTransform(SourceComponent.Get(), TimeSinceActive);
|
|
}
|
|
|
|
void FGCS_TraceState::UpdatePreviousTransform(const FTransform& Transform)
|
|
{
|
|
if (TransformsOverTime.Num() == 0)
|
|
{
|
|
TransformsOverTime.Add(Transform);
|
|
}
|
|
else
|
|
{
|
|
TransformsOverTime[0] = Transform;
|
|
}
|
|
}
|