Files
UnrealEngineUWP/Engine/Plugins/Runtime/SmartObjects/Source/SmartObjectsModule/Private/Annotations/SmartObjectSlotEntranceAnnotation.cpp
mikko mononen 1ca6e4407c Smart Objects: Added way to project navigation locations on ground and to check collisions between nav location and slot.
- Changed entry annotation to navigation annotation
- Added option for nav annotations to project location on ground
- Added option and settings for nav annotations to check simple trajectory collisions towards slot location
- Added logic in entry location query to project on ground and check trajectory collisions
- Added physics settings struct that handles common query combinations
- Added USmartObjectSlotValidationFilter to define shareable settings for validation (kinda similar to nav query filter)
- Fixed double rendering of preview actor/mesh in SO editor
- added debug draw for the new features

#jira UE-174418
#preflight 641036e470639dfc943ed981

[CL 24632583 by mikko mononen in ue5-main branch]
2023-03-14 06:26:29 -04:00

491 lines
21 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "Annotations/SmartObjectSlotEntranceAnnotation.h"
#include "SmartObjectSubsystem.h"
#include "SmartObjectDefinition.h"
#include "SmartObjectVisualizationContext.h"
#include "SceneManagement.h" // FPrimitiveDrawInterface
#include "NavigationSystem.h"
#include "NavigationData.h"
#include "AI/Navigation/NavAgentInterface.h"
#include "SmartObjectSettings.h"
#if WITH_GAMEPLAY_DEBUGGER
#include "GameplayDebuggerCategory.h"
#endif
#include UE_INLINE_GENERATED_CPP_BY_NAME(SmartObjectSlotEntranceAnnotation)
namespace UE::SmartObject::Annotations
{
const ANavigationData* GetDefaultNavData(const UWorld& World)
{
const UNavigationSystemV1* NavSys = FNavigationSystem::GetCurrent<UNavigationSystemV1>(&World);
if (!NavSys)
{
return nullptr;
}
return NavSys->GetDefaultNavDataInstance();
}
const ANavigationData* GetNavDataForActor(const UWorld& World, const AActor* UserActor)
{
if (const UNavigationSystemV1* NavSys = FNavigationSystem::GetCurrent<UNavigationSystemV1>(&World))
{
const INavAgentInterface* NavAgent = Cast<INavAgentInterface>(UserActor);
if (NavAgent)
{
const FNavAgentProperties& NavAgentProps = NavAgent->GetNavAgentPropertiesRef();
return NavSys->GetNavDataForProps(NavAgentProps, NavAgent->GetNavAgentLocation());
}
return NavSys->GetDefaultNavDataInstance();
}
return nullptr;
}
bool ProjectNavigationLocation(const ANavigationData& NavData, const FVector Location, const FBox& SearchBounds, const FSharedConstNavQueryFilter& NavigationFilter, const AActor* InstigatorActor, FNavLocation& OutNavLocation)
{
return NavData.ProjectPoint(Location, OutNavLocation, SearchBounds.GetExtent(), NavigationFilter, InstigatorActor)
&& OutNavLocation.HasNodeRef()
&& SearchBounds.IsInsideOrOn(OutNavLocation.Location);
}
bool TraceGroundLocation(const UWorld& World, const FVector Location, const FBox& SearchBounds, const FSmartObjectTraceParams& TraceParameters, const FCollisionQueryParams& CollisionQueryParams, FVector& OutGroundLocation)
{
const FVector TraceStart(Location.X, Location.Y, SearchBounds.Max.Z);
const FVector TraceEnd(Location.X, Location.Y, SearchBounds.Min.Z);
FHitResult HitResult;
bool bHasHit = false;
if (TraceParameters.Type == ESmartObjectTraceType::ByChannel)
{
bHasHit = World.LineTraceSingleByChannel(HitResult, TraceStart, TraceEnd, UEngineTypes::ConvertToCollisionChannel(TraceParameters.TraceChannel), CollisionQueryParams);
}
else if (TraceParameters.Type == ESmartObjectTraceType::ByProfile)
{
bHasHit = World.LineTraceSingleByProfile(HitResult, TraceStart, TraceEnd, TraceParameters.CollisionProfile.Name, CollisionQueryParams);
}
else if (TraceParameters.Type == ESmartObjectTraceType::ByObjectTypes)
{
const FCollisionObjectQueryParams ObjectQueryParams(TraceParameters.ObjectTypes);
bHasHit = World.LineTraceSingleByObjectType(HitResult, TraceStart, TraceEnd, ObjectQueryParams, CollisionQueryParams);
}
if (bHasHit)
{
OutGroundLocation = HitResult.Location;
return true;
}
return false;
}
bool TestCollidersOverlap(const UWorld& World, TConstArrayView<FSmartObjectAnnotationCollider> Colliders, const FSmartObjectTraceParams& TraceParameters, const FCollisionQueryParams& CollisionQueryParams)
{
bool bHasHit = false;
for (const FSmartObjectAnnotationCollider& Collider : Colliders)
{
if (TraceParameters.Type == ESmartObjectTraceType::ByChannel)
{
bHasHit = World.OverlapBlockingTestByChannel(Collider.Location, Collider.Rotation, UEngineTypes::ConvertToCollisionChannel(TraceParameters.TraceChannel), Collider.CollisionShape, CollisionQueryParams);
}
else if (TraceParameters.Type == ESmartObjectTraceType::ByProfile)
{
bHasHit = World.OverlapBlockingTestByProfile(Collider.Location, Collider.Rotation, TraceParameters.CollisionProfile.Name, Collider.CollisionShape, CollisionQueryParams);
}
else if (TraceParameters.Type == ESmartObjectTraceType::ByObjectTypes)
{
// @todo: there's no blocking variant, and when tried to implement, it did not work.
const FCollisionObjectQueryParams ObjectQueryParams(TraceParameters.ObjectTypes);
bHasHit = World.OverlapAnyTestByObjectType(Collider.Location, Collider.Rotation, ObjectQueryParams, Collider.CollisionShape, CollisionQueryParams);
}
if (bHasHit)
{
break;
}
}
return bHasHit;
}
static constexpr FColor EntryColor(0, 64, 192);
static constexpr FColor CollisionColor(255, 255, 255, 128);
static constexpr FColor InvalidEntryColor(192, 32, 16);
struct FVisualizationData
{
FVector SlotLocation;
FVector MarkerLocation;
FVector MarkerAxisX;
FVector MarkerAxisY;
FVector ValidatedLocation;
FVector GroundLocationStart;
FVector GroundLocationEnd;
TArray<FSmartObjectAnnotationCollider> Colliders;
FLinearColor MarkerColor = EntryColor;
FLinearColor ColliderColor = CollisionColor;
};
const USmartObjectSlotValidationFilter* GetPreviewValidationFilter()
{
const TSubclassOf<USmartObjectSlotValidationFilter> DefaultValidationFilterClass = GetDefault<USmartObjectSettings>()->PreviewValidationFilter;
const USmartObjectSlotValidationFilter* DefaultFilter = DefaultValidationFilterClass.GetDefaultObject();
if (!DefaultFilter)
{
DefaultFilter = GetDefault<USmartObjectSlotValidationFilter>();
}
return DefaultFilter;
}
void UpdateVisualizationLogic(const UWorld& World, const FSmartObjectSlotEntranceAnnotation& Annotation, const FTransform& SlotTransform, const FTransform& AnnotationTransform, const AActor* PreviewActor, FVisualizationData& OutData)
{
const ANavigationData* DefaultNavData = GetDefaultNavData(World);
const USmartObjectSlotValidationFilter* DefaultFilter = GetPreviewValidationFilter();
check(DefaultFilter);
const FSmartObjectTraceParams& GroundTraceParameters = DefaultFilter->GetGroundTraceParameters();
const FSmartObjectTraceParams& TransitionTraceParameters = DefaultFilter->GetTransitionTraceParameters();
FCollisionQueryParams GroundTraceQueryParams(SCENE_QUERY_STAT(SmartObjectTrace), GroundTraceParameters.bTraceComplex);
FCollisionQueryParams TransitionTraceQueryParams(SCENE_QUERY_STAT(SmartObjectTrace), TransitionTraceParameters.bTraceComplex);
if (PreviewActor)
{
GroundTraceQueryParams.AddIgnoredActor(PreviewActor);
TransitionTraceQueryParams.AddIgnoredActor(PreviewActor);
}
const FVector AnnotationWorldLocation = AnnotationTransform.GetTranslation();
const FVector AxisX = AnnotationTransform.GetUnitAxis(EAxis::X);
const FVector AxisY = AnnotationTransform.GetUnitAxis(EAxis::Y);
OutData.SlotLocation = SlotTransform.GetLocation();
OutData.MarkerColor = EntryColor;
OutData.ColliderColor = CollisionColor;
OutData.MarkerLocation = AnnotationWorldLocation;
OutData.MarkerAxisX = AxisX;
OutData.MarkerAxisY = AxisY;
const FBox SearchBounds(AnnotationWorldLocation - DefaultFilter->GetSearchExtents(), AnnotationWorldLocation + DefaultFilter->GetSearchExtents());
OutData.ValidatedLocation = AnnotationWorldLocation;
// Validate location on navmesh
// @todo: add visualization for missing navdata.
if (DefaultNavData)
{
FNavLocation NavLocation;
if (ProjectNavigationLocation(*DefaultNavData, AnnotationWorldLocation, SearchBounds, {}, /*RequesterActor*/nullptr, NavLocation))
{
OutData.ValidatedLocation = NavLocation.Location;
}
else
{
OutData.MarkerColor = InvalidEntryColor;
}
}
// Try to trace the slot on location on ground.
if (Annotation.bTraceGroundLocation)
{
FVector GroundLocation;
if (TraceGroundLocation(World, OutData.ValidatedLocation, SearchBounds, GroundTraceParameters, GroundTraceQueryParams, GroundLocation))
{
OutData.ValidatedLocation = GroundLocation;
}
else
{
OutData.MarkerColor = InvalidEntryColor;
}
}
if (Annotation.bCheckTransitionTrajectory)
{
Annotation.GetTrajectoryColliders(SlotTransform, OutData.Colliders);
if (TestCollidersOverlap(World, OutData.Colliders, TransitionTraceParameters, TransitionTraceQueryParams))
{
OutData.ColliderColor = InvalidEntryColor;
}
}
OutData.GroundLocationStart = FVector(OutData.ValidatedLocation.X, OutData.ValidatedLocation.Y, FMath::Max(OutData.ValidatedLocation.Z, OutData.MarkerLocation.Z));
OutData.GroundLocationEnd = FVector(OutData.ValidatedLocation.X, OutData.ValidatedLocation.Y, FMath::Min(OutData.ValidatedLocation.Z, OutData.MarkerLocation.Z));
}
} // UE::SmartObject::Annotations
#if WITH_EDITOR
void FSmartObjectSlotEntranceAnnotation::DrawVisualization(FSmartObjectVisualizationContext& VisContext) const
{
constexpr FVector::FReal MarkerRadius = 20.0;
constexpr FVector::FReal TickSize = 5.0;
constexpr FVector::FReal MinArrowDrawDistance = 20.0;
constexpr float DepthBias = 2.0f;
constexpr bool ScreenSpace = true;
const FSmartObjectSlotIndex SlotIndex(VisContext.SlotIndex);
const TOptional<FTransform> SlotTransform = VisContext.Definition.GetSlotTransform(VisContext.OwnerLocalToWorld, SlotIndex);
if (!SlotTransform.IsSet())
{
return;
}
const TOptional<FTransform> AnnotationTransform = GetWorldTransform(*SlotTransform);
if (!AnnotationTransform.IsSet())
{
return;
}
UE::SmartObject::Annotations::FVisualizationData Data;
UE::SmartObject::Annotations::UpdateVisualizationLogic(VisContext.World, *this, *SlotTransform, *AnnotationTransform, VisContext.PreviewActor, Data);
// Draw validated location in relation to the marker locations.
if (FVector::Distance(Data.MarkerLocation, Data.ValidatedLocation) > UE_KINDA_SMALL_NUMBER)
{
VisContext.PDI->DrawTranslucentLine(Data.GroundLocationStart, Data.GroundLocationEnd, Data.MarkerColor, SDPG_World, 1.0f, DepthBias, ScreenSpace);
VisContext.PDI->DrawTranslucentLine(Data.ValidatedLocation - Data.MarkerAxisX * TickSize * 0.5, Data.ValidatedLocation + Data.MarkerAxisX * TickSize * 0.5, Data.MarkerColor, SDPG_World, 1.0f, DepthBias, ScreenSpace);
VisContext.PDI->DrawTranslucentLine(Data.ValidatedLocation - Data.MarkerAxisY * TickSize * 0.5, Data.ValidatedLocation + Data.MarkerAxisY * TickSize * 0.5, Data.MarkerColor, SDPG_World, 1.0f, DepthBias, ScreenSpace);
}
if (VisContext.bIsAnnotationSelected)
{
Data.MarkerColor = VisContext.SelectedColor;
}
if (bIsEntry)
{
const FVector V0 = Data.MarkerLocation + Data.MarkerAxisX * MarkerRadius;
const FVector V1 = Data.MarkerLocation + Data.MarkerAxisX * MarkerRadius * 0.25 + Data.MarkerAxisY * MarkerRadius;
const FVector V2 = Data.MarkerLocation + Data.MarkerAxisX * MarkerRadius * 0.25 - Data.MarkerAxisY * MarkerRadius;
const FVector V3 = Data.MarkerLocation + Data.MarkerAxisY * MarkerRadius;
const FVector V4 = Data.MarkerLocation - Data.MarkerAxisY * MarkerRadius;
VisContext.PDI->DrawTranslucentLine(V0, V1, Data.MarkerColor, SDPG_World, 4.0f, DepthBias, ScreenSpace);
VisContext.PDI->DrawTranslucentLine(V0, V2, Data.MarkerColor, SDPG_World, 4.0f, DepthBias, ScreenSpace);
VisContext.PDI->DrawTranslucentLine(V1, V3, Data.MarkerColor, SDPG_World, 4.0f, DepthBias, ScreenSpace);
VisContext.PDI->DrawTranslucentLine(V2, V4, Data.MarkerColor, SDPG_World, 4.0f, DepthBias, ScreenSpace);
}
if (bIsExit)
{
const FVector V1 = Data.MarkerLocation - Data.MarkerAxisX * MarkerRadius * 0.75 + Data.MarkerAxisY * MarkerRadius;
const FVector V2 = Data.MarkerLocation - Data.MarkerAxisX * MarkerRadius * 0.75 - Data.MarkerAxisY * MarkerRadius;
const FVector V3 = Data.MarkerLocation + Data.MarkerAxisY * MarkerRadius;
const FVector V4 = Data.MarkerLocation - Data.MarkerAxisY * MarkerRadius;
VisContext.PDI->DrawTranslucentLine(V1, V2, Data.MarkerColor, SDPG_World, 4.0f, DepthBias, ScreenSpace);
VisContext.PDI->DrawTranslucentLine(V1, V3, Data.MarkerColor, SDPG_World, 4.0f, DepthBias, ScreenSpace);
VisContext.PDI->DrawTranslucentLine(V2, V4, Data.MarkerColor, SDPG_World, 4.0f, DepthBias, ScreenSpace);
}
if (!Data.Colliders.IsEmpty())
{
for (const FSmartObjectAnnotationCollider& Collider : Data.Colliders)
{
if (Collider.CollisionShape.IsCapsule())
{
DrawWireCapsule(VisContext.PDI, Collider.Location, Collider.Rotation.GetAxisX(), Collider.Rotation.GetAxisY(), Collider.Rotation.GetAxisZ(),
Data.ColliderColor, Collider.CollisionShape.GetCapsuleRadius(), Collider.CollisionShape.GetCapsuleHalfHeight(), 12, SDPG_World, 1.0f, DepthBias, ScreenSpace);
}
else if (Collider.CollisionShape.IsBox())
{
DrawOrientedWireBox(VisContext.PDI, Collider.Location, Collider.Rotation.GetAxisX(), Collider.Rotation.GetAxisY(), Collider.Rotation.GetAxisZ(),
Collider.CollisionShape.GetExtent(), Data.ColliderColor, SDPG_World, 1.0f, DepthBias, ScreenSpace);
}
else if (Collider.CollisionShape.IsSphere())
{
DrawWireSphere(VisContext.PDI, Collider.Location, Data.ColliderColor, Collider.CollisionShape.GetSphereRadius(), 12, SDPG_World, 1.0f, DepthBias, ScreenSpace);
}
}
}
// Tick at the center.
VisContext.PDI->DrawTranslucentLine(Data.MarkerLocation - Data.MarkerAxisX * TickSize, Data.MarkerLocation + Data.MarkerAxisX * TickSize, Data.MarkerColor, SDPG_World, 1.0f, DepthBias, ScreenSpace);
VisContext.PDI->DrawTranslucentLine(Data.MarkerLocation - Data.MarkerAxisY * TickSize, Data.MarkerLocation + Data.MarkerAxisY * TickSize, Data.MarkerColor, SDPG_World, 1.0f, DepthBias, ScreenSpace);
// Arrow pointing at the the slot, if far enough from the slot.
if (FVector::DistSquared(Data.MarkerLocation, Data.SlotLocation) > FMath::Square(MinArrowDrawDistance))
{
VisContext.DrawArrow(Data.MarkerLocation, Data.SlotLocation, Data.MarkerColor, 5.0f, 5.0f, /*DepthPrioGroup*/0, /*Thickness*/1.0f, DepthBias, ScreenSpace);
}
}
void FSmartObjectSlotEntranceAnnotation::DrawVisualizationHUD(FSmartObjectVisualizationContext& VisContext) const
{
// @tooo: move this into a setting.
constexpr FVector::FReal MaxDrawDistance = 1500.0;
constexpr FVector::FReal FadeDrawDistance = MaxDrawDistance * 0.75;
const FSmartObjectSlotIndex SlotIndex(VisContext.SlotIndex);
const TOptional<FTransform> SlotTransform = VisContext.Definition.GetSlotTransform(VisContext.OwnerLocalToWorld, SlotIndex);
if (SlotTransform.IsSet())
{
TOptional<FTransform> AnnotationTransform = GetWorldTransform(*SlotTransform);
if (AnnotationTransform.IsSet())
{
const FVector AnnotationWorldLocation = AnnotationTransform->GetTranslation();
const FVector::FReal Distance = VisContext.GetDistanceToCamera(AnnotationWorldLocation);
if (Distance < MaxDrawDistance)
{
FString Text = FString::Printf(TEXT("S%d NAV%d \n"), VisContext.SlotIndex, VisContext.AnnotationIndex);
if (Tag.IsValid())
{
Text += Tag.ToString();
}
FLinearColor Color = FLinearColor::White;
Color.A = FMath::Clamp(1.0 - (Distance - FadeDrawDistance) / (MaxDrawDistance - FadeDrawDistance), 0.0, 1.0);
VisContext.DrawString(AnnotationWorldLocation, *Text, Color);
}
}
}
}
void FSmartObjectSlotEntranceAnnotation::AdjustWorldTransform(const FTransform& SlotTransform, const FVector& DeltaTranslation, const FRotator& DeltaRotation)
{
if (!DeltaTranslation.IsZero())
{
const FVector LocalTranslation = SlotTransform.InverseTransformVector(DeltaTranslation);
Offset += FVector3f(LocalTranslation);
}
if (!DeltaRotation.IsZero())
{
const FRotator3f LocalRotation = FRotator3f(SlotTransform.InverseTransformRotation(DeltaRotation.Quaternion()).Rotator());
Rotation += LocalRotation;
Rotation.Normalize();
}
}
#endif // WITH_EDITOR
void FSmartObjectSlotEntranceAnnotation::GetTrajectoryColliders(const FTransform& SlotTransform, TArray<FSmartObjectAnnotationCollider>& OutColliders) const
{
const FVector SlotWorldLocation = SlotTransform.GetLocation();
const FVector AnnotationWorldLocation = SlotTransform.TransformPosition(FVector(Offset));
const FVector SegmentStart = AnnotationWorldLocation + FVector(0, 0, TrajectoryStartHeightOffset);
const FVector SegmentEnd = SlotWorldLocation + FVector(0, 0, TrajectorySlotHeightOffset);
const FVector Center = (SegmentStart + SegmentEnd) * 0.5;
const FVector Dir = SegmentEnd - SegmentStart;
FVector Up;
float Length = 0.0f;
Dir.ToDirectionAndLength(Up, Length);
FSmartObjectAnnotationCollider& Collider = OutColliders.AddDefaulted_GetRef();
Collider.Location = Center;
Collider.Rotation = FQuat::FindBetweenNormals(FVector::UpVector, Up);
Collider.CollisionShape = FCollisionShape::MakeCapsule(TransitionCheckRadius, Length * 0.5f + TransitionCheckRadius);
}
TOptional<FTransform> FSmartObjectSlotEntranceAnnotation::GetWorldTransform(const FTransform& SlotTransform) const
{
const FTransform LocalTransform = FTransform(FRotator(Rotation), FVector(Offset));
return TOptional(LocalTransform * SlotTransform);
}
FVector FSmartObjectSlotEntranceAnnotation::GetWorldLocation(const FTransform& SlotTransform) const
{
return SlotTransform.TransformPosition(FVector(Offset));
}
FRotator FSmartObjectSlotEntranceAnnotation::GetWorldRotation(const FTransform& SlotTransform) const
{
return SlotTransform.TransformRotation(FQuat(Rotation.Quaternion())).Rotator();
}
#if WITH_GAMEPLAY_DEBUGGER
void FSmartObjectSlotEntranceAnnotation::CollectDataForGameplayDebugger(FGameplayDebuggerCategory& Category, const FTransform& SlotTransform, const AActor* SmartObjectOwnerActor, const FVector ViewLocation, const FVector ViewDirection, const AActor* DebugActor) const
{
constexpr FVector::FReal MarkerRadius = 20.0;
constexpr FVector::FReal TickSize = 5.0;
constexpr FVector::FReal MinArrowDrawDistance = 20.0;
const UWorld* World = Category.GetWorldFromReplicator();
if (!World)
{
return;
}
const TOptional<FTransform> AnnotationTransform = GetWorldTransform(SlotTransform);
if (!AnnotationTransform.IsSet())
{
return;
}
UE::SmartObject::Annotations::FVisualizationData Data;
UE::SmartObject::Annotations::UpdateVisualizationLogic(*World, *this, SlotTransform, *AnnotationTransform, SmartObjectOwnerActor, Data);
// Draw validated location in relation to the marker locations.
if (FVector::Distance(Data.MarkerLocation, Data.ValidatedLocation) > UE_KINDA_SMALL_NUMBER)
{
Category.AddShape(FGameplayDebuggerShape::MakeSegmentList( {
Data.GroundLocationStart, Data.GroundLocationEnd,
Data.ValidatedLocation - Data.MarkerAxisX * TickSize * 0.5, Data.ValidatedLocation + Data.MarkerAxisX * TickSize * 0.5,
Data.ValidatedLocation - Data.MarkerAxisY * TickSize * 0.5, Data.ValidatedLocation + Data.MarkerAxisY * TickSize * 0.5
}, 1.0f, Data.MarkerColor.ToFColor(/*bSRGB*/true)));
}
if (bIsEntry)
{
Category.AddShape(FGameplayDebuggerShape::MakePolyline({
Data.MarkerLocation + Data.MarkerAxisY * MarkerRadius,
Data.MarkerLocation + Data.MarkerAxisX * MarkerRadius * 0.25 + Data.MarkerAxisY * MarkerRadius,
Data.MarkerLocation + Data.MarkerAxisX * MarkerRadius,
Data.MarkerLocation + Data.MarkerAxisX * MarkerRadius * 0.25 - Data.MarkerAxisY * MarkerRadius,
Data.MarkerLocation - Data.MarkerAxisY * MarkerRadius
}, 4.0f, Data.MarkerColor.ToFColor(/*bSRGB*/true)));
}
if (bIsExit)
{
Category.AddShape(FGameplayDebuggerShape::MakePolyline({
Data.MarkerLocation + Data.MarkerAxisY * MarkerRadius,
Data.MarkerLocation - Data.MarkerAxisX * MarkerRadius * 0.5 + Data.MarkerAxisY * MarkerRadius,
Data.MarkerLocation - Data.MarkerAxisX * MarkerRadius * 0.5 - Data.MarkerAxisY * MarkerRadius,
Data.MarkerLocation - Data.MarkerAxisY * MarkerRadius
}, 4.0f, Data.MarkerColor.ToFColor(/*bSRGB*/true)));
}
if (!Data.Colliders.IsEmpty())
{
for (const FSmartObjectAnnotationCollider& Collider : Data.Colliders)
{
if (Collider.CollisionShape.IsCapsule())
{
Category.AddShape(FGameplayDebuggerShape::MakeCapsule(Collider.Location, Collider.Rotation.Rotator(), Collider.CollisionShape.GetCapsuleRadius(), Collider.CollisionShape.GetCapsuleHalfHeight(), Data.ColliderColor.ToFColor(/*bSRGB*/true)));
}
else if (Collider.CollisionShape.IsBox())
{
Category.AddShape(FGameplayDebuggerShape::MakeBox(Collider.Location, Collider.Rotation.Rotator(), Collider.CollisionShape.GetExtent(), Data.ColliderColor.ToFColor(/*bSRGB*/true)));
}
else if (Collider.CollisionShape.IsSphere())
{
Category.AddShape(FGameplayDebuggerShape::MakePoint(Collider.Location, Collider.CollisionShape.GetSphereRadius(), Data.ColliderColor.ToFColor(/*bSRGB*/true)));
}
}
}
// Tick at the center.
Category.AddShape(FGameplayDebuggerShape::MakeSegmentList( {
Data.MarkerLocation - Data.MarkerAxisX * TickSize,
Data.MarkerLocation + Data.MarkerAxisX * TickSize,
Data.MarkerLocation - Data.MarkerAxisY * TickSize,
Data.MarkerLocation + Data.MarkerAxisY * TickSize
}, 1.0f, Data.MarkerColor.ToFColor(/*bSRGB*/true)));
// Arrow pointing at the the slot, if far enough from the slot.
if (FVector::DistSquared(Data.MarkerLocation, Data.SlotLocation) > FMath::Square(MinArrowDrawDistance))
{
Category.AddShape(FGameplayDebuggerShape::MakeSegment(Data.MarkerLocation, Data.SlotLocation, 1.0f, Data.MarkerColor.ToFColor(/*bSRGB*/true)));
}
}
#endif // WITH_GAMEPLAY_DEBUGGER