Files
PHY/Plugins/GCS/Source/GenericCombatSystem/Private/Collision/GCS_TraceStructLibrary.cpp
2026-03-03 01:23:02 +08:00

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;
}
}