2023-03-14 06:26:29 -04:00
// 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"
2023-03-27 08:22:19 -04:00
# include "SmartObjectUserComponent.h"
2023-04-14 09:28:04 -04:00
# include "PhysicsEngine/ClusterUnionComponent.h"
2023-03-14 06:26:29 -04:00
# 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 ;
2023-06-08 05:38:09 -04:00
TArray < FOverlapResult > Overlaps ;
2023-03-14 06:26:29 -04:00
for ( const FSmartObjectAnnotationCollider & Collider : Colliders )
{
2023-06-08 05:38:09 -04:00
Overlaps . Reset ( ) ;
2023-03-14 06:26:29 -04:00
if ( TraceParameters . Type = = ESmartObjectTraceType : : ByChannel )
{
2023-06-08 05:38:09 -04:00
bHasHit = World . OverlapMultiByChannel ( Overlaps , Collider . Location , Collider . Rotation , UEngineTypes : : ConvertToCollisionChannel ( TraceParameters . TraceChannel ) , Collider . CollisionShape , CollisionQueryParams ) ;
2023-03-14 06:26:29 -04:00
}
else if ( TraceParameters . Type = = ESmartObjectTraceType : : ByProfile )
{
2023-06-08 05:38:09 -04:00
bHasHit = World . OverlapMultiByProfile ( Overlaps , Collider . Location , Collider . Rotation , TraceParameters . CollisionProfile . Name , Collider . CollisionShape , CollisionQueryParams ) ;
2023-03-14 06:26:29 -04:00
}
else if ( TraceParameters . Type = = ESmartObjectTraceType : : ByObjectTypes )
{
2023-06-08 05:38:09 -04:00
// Overlap tests with object types will only ever return non-blocking results (due to historical reasons), so using the any variant here (blocking does not exist).
2023-03-14 06:26:29 -04:00
const FCollisionObjectQueryParams ObjectQueryParams ( TraceParameters . ObjectTypes ) ;
2023-06-08 05:38:09 -04:00
bHasHit = World . OverlapMultiByObjectType ( Overlaps , Collider . Location , Collider . Rotation , ObjectQueryParams , Collider . CollisionShape , CollisionQueryParams ) ;
2023-03-14 06:26:29 -04:00
}
2023-06-08 05:38:09 -04:00
if ( bHasHit )
2023-03-14 06:26:29 -04:00
{
break ;
2023-06-08 05:38:09 -04:00
}
2023-03-14 06:26:29 -04:00
}
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 ;
} ;
2023-03-27 08:22:19 -04:00
void UpdateVisualizationLogic ( const UWorld & World , const FSmartObjectSlotEntranceAnnotation & Annotation , const FTransform & SlotTransform , const FTransform & AnnotationTransform ,
const AActor * PreviewSmartObjectActor , const AActor * PreviewUserActor , TSubclassOf < USmartObjectSlotValidationFilter > PreviewValidationFilterClass , FVisualizationData & OutData )
2023-03-14 06:26:29 -04:00
{
2023-03-27 08:22:19 -04:00
const USmartObjectSlotValidationFilter * PreviewValidationFilter = PreviewValidationFilterClass . GetDefaultObject ( ) ;
if ( ! PreviewValidationFilter )
{
PreviewValidationFilter = GetDefault < USmartObjectSlotValidationFilter > ( ) ;
}
2023-03-14 06:26:29 -04:00
2023-03-27 08:22:19 -04:00
const ANavigationData * DefaultNavData = GetDefaultNavData ( World ) ;
const FSmartObjectSlotValidationParams & ValidationParams = PreviewValidationFilter - > GetEntryValidationParams ( ) ;
const FSmartObjectTraceParams & GroundTraceParameters = ValidationParams . GetGroundTraceParameters ( ) ;
const FSmartObjectTraceParams & TransitionTraceParameters = ValidationParams . GetTransitionTraceParameters ( ) ;
2023-04-18 13:26:22 -04:00
2023-03-14 06:26:29 -04:00
FCollisionQueryParams GroundTraceQueryParams ( SCENE_QUERY_STAT ( SmartObjectTrace ) , GroundTraceParameters . bTraceComplex ) ;
FCollisionQueryParams TransitionTraceQueryParams ( SCENE_QUERY_STAT ( SmartObjectTrace ) , TransitionTraceParameters . bTraceComplex ) ;
2023-04-18 13:26:22 -04:00
GroundTraceQueryParams . bIgnoreTouches = true ;
TransitionTraceQueryParams . bIgnoreTouches = true ;
2023-03-27 08:22:19 -04:00
if ( PreviewSmartObjectActor )
2023-03-14 06:26:29 -04:00
{
2023-03-27 08:22:19 -04:00
GroundTraceQueryParams . AddIgnoredActor ( PreviewSmartObjectActor ) ;
TransitionTraceQueryParams . AddIgnoredActor ( PreviewSmartObjectActor ) ;
}
if ( PreviewUserActor )
{
GroundTraceQueryParams . AddIgnoredActor ( PreviewUserActor ) ;
TransitionTraceQueryParams . AddIgnoredActor ( PreviewUserActor ) ;
2023-03-14 06:26:29 -04:00
}
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 ;
2023-03-27 08:22:19 -04:00
const FBox SearchBounds ( AnnotationWorldLocation - ValidationParams . GetSearchExtents ( ) , AnnotationWorldLocation + ValidationParams . GetSearchExtents ( ) ) ;
2023-03-14 06:26:29 -04:00
OutData . ValidatedLocation = AnnotationWorldLocation ;
// Validate location on navmesh
// @todo: add visualization for missing navdata.
if ( DefaultNavData )
{
2023-03-27 08:22:19 -04:00
FSharedConstNavQueryFilter NavigationFilter ;
if ( ValidationParams . GetNavigationFilter ( ) )
{
NavigationFilter = UNavigationQueryFilter : : GetQueryFilter ( * DefaultNavData , nullptr , ValidationParams . GetNavigationFilter ( ) ) ;
}
2023-03-14 06:26:29 -04:00
FNavLocation NavLocation ;
2023-03-27 08:22:19 -04:00
if ( ProjectNavigationLocation ( * DefaultNavData , AnnotationWorldLocation , SearchBounds , NavigationFilter , /*RequesterActor*/ nullptr , NavLocation ) )
2023-03-14 06:26:29 -04:00
{
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 ;
2023-07-18 09:00:26 -04:00
const FTransform SlotTransform = VisContext . Definition . GetSlotWorldTransform ( VisContext . SlotIndex , VisContext . OwnerLocalToWorld ) ;
const FTransform AnnotationTransform = GetAnnotationWorldTransform ( SlotTransform ) ;
2023-03-14 06:26:29 -04:00
UE : : SmartObject : : Annotations : : FVisualizationData Data ;
2023-07-18 09:00:26 -04:00
UE : : SmartObject : : Annotations : : UpdateVisualizationLogic ( VisContext . World , * this , SlotTransform , AnnotationTransform ,
2023-03-27 08:22:19 -04:00
VisContext . PreviewActor , nullptr , VisContext . PreviewValidationFilterClass , Data ) ;
2023-03-14 06:26:29 -04:00
// 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 ;
2023-07-18 09:00:26 -04:00
const FTransform SlotTransform = VisContext . Definition . GetSlotWorldTransform ( VisContext . SlotIndex , VisContext . OwnerLocalToWorld ) ;
const FTransform AnnotationTransform = GetAnnotationWorldTransform ( SlotTransform ) ;
const FVector AnnotationWorldLocation = AnnotationTransform . GetTranslation ( ) ;
2023-03-14 06:26:29 -04:00
2023-07-18 09:00:26 -04:00
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 ( SelectionPriority ! = ESmartObjectEntrancePriority : : Normal )
{
Text + = UEnum : : GetDisplayValueAsText ( SelectionPriority ) . ToString ( ) ;
2023-03-14 06:26:29 -04:00
}
2023-07-18 09:00:26 -04:00
if ( Tags . IsValid ( ) )
{
Text + = Tags . ToString ( ) ;
}
FLinearColor Color = FLinearColor : : White ;
Color . A = FMath : : Clamp ( 1.0 - ( Distance - FadeDrawDistance ) / ( MaxDrawDistance - FadeDrawDistance ) , 0.0 , 1.0 ) ;
VisContext . DrawString ( AnnotationWorldLocation , * Text , Color ) ;
2023-03-14 06:26:29 -04:00
}
}
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 ) ;
}
2023-07-18 09:00:26 -04:00
FTransform FSmartObjectSlotEntranceAnnotation : : GetAnnotationWorldTransform ( const FTransform & SlotTransform ) const
2023-03-14 06:26:29 -04:00
{
const FTransform LocalTransform = FTransform ( FRotator ( Rotation ) , FVector ( Offset ) ) ;
2023-07-18 09:00:26 -04:00
return LocalTransform * SlotTransform ;
2023-03-14 06:26:29 -04:00
}
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 ( ) ;
}
2023-06-06 09:07:47 -04:00
# if WITH_EDITORONLY_DATA
void FSmartObjectSlotEntranceAnnotation : : PostSerialize ( const FArchive & Ar )
{
PRAGMA_DISABLE_DEPRECATION_WARNINGS
if ( Tag_DEPRECATED . IsValid ( ) )
{
Tags . AddTag ( Tag_DEPRECATED ) ;
Tag_DEPRECATED = FGameplayTag ( ) ;
}
PRAGMA_ENABLE_DEPRECATION_WARNINGS
}
# endif
2023-03-14 06:26:29 -04:00
# if WITH_GAMEPLAY_DEBUGGER
2023-03-27 08:22:19 -04:00
void FSmartObjectSlotEntranceAnnotation : : CollectDataForGameplayDebugger ( FSmartObjectAnnotationGameplayDebugContext & DebugContext ) const
2023-03-14 06:26:29 -04:00
{
constexpr FVector : : FReal MarkerRadius = 20.0 ;
constexpr FVector : : FReal TickSize = 5.0 ;
constexpr FVector : : FReal MinArrowDrawDistance = 20.0 ;
2023-03-27 08:22:19 -04:00
const UWorld * World = DebugContext . Category . GetWorldFromReplicator ( ) ;
2023-03-14 06:26:29 -04:00
if ( ! World )
{
return ;
}
2023-07-18 09:00:26 -04:00
const FTransform AnnotationTransform = GetAnnotationWorldTransform ( DebugContext . SlotTransform ) ;
2023-03-14 06:26:29 -04:00
2023-03-27 08:22:19 -04:00
TSubclassOf < USmartObjectSlotValidationFilter > ValidationFilterClass ;
if ( DebugContext . DebugActor )
{
// If user actor is present, try to query some data automatically from interfaces and components.
if ( ! ValidationFilterClass . Get ( ) )
{
if ( const USmartObjectUserComponent * UserComponent = DebugContext . DebugActor - > GetComponentByClass < USmartObjectUserComponent > ( ) )
{
if ( UserComponent - > GetValidationFilter ( ) . Get ( ) )
{
ValidationFilterClass = UserComponent - > GetValidationFilter ( ) ;
}
}
}
}
2023-03-14 06:26:29 -04:00
UE : : SmartObject : : Annotations : : FVisualizationData Data ;
2023-07-18 09:00:26 -04:00
UE : : SmartObject : : Annotations : : UpdateVisualizationLogic ( * World , * this , DebugContext . SlotTransform , AnnotationTransform ,
2023-03-27 08:22:19 -04:00
DebugContext . SmartObjectOwnerActor , DebugContext . DebugActor , ValidationFilterClass , Data ) ;
2023-03-14 06:26:29 -04:00
// Draw validated location in relation to the marker locations.
if ( FVector : : Distance ( Data . MarkerLocation , Data . ValidatedLocation ) > UE_KINDA_SMALL_NUMBER )
{
2023-03-27 08:22:19 -04:00
DebugContext . Category . AddShape ( FGameplayDebuggerShape : : MakeSegmentList ( {
2023-03-14 06:26:29 -04:00
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 )
{
2023-03-27 08:22:19 -04:00
DebugContext . Category . AddShape ( FGameplayDebuggerShape : : MakePolyline ( {
2023-03-14 06:26:29 -04:00
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 )
{
2023-03-27 08:22:19 -04:00
DebugContext . Category . AddShape ( FGameplayDebuggerShape : : MakePolyline ( {
2023-03-14 06:26:29 -04:00
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 ( ) )
{
2023-03-27 08:22:19 -04:00
DebugContext . Category . AddShape ( FGameplayDebuggerShape : : MakeCapsule ( Collider . Location , Collider . Rotation . Rotator ( ) , Collider . CollisionShape . GetCapsuleRadius ( ) , Collider . CollisionShape . GetCapsuleHalfHeight ( ) , Data . ColliderColor . ToFColor ( /*bSRGB*/ true ) ) ) ;
2023-03-14 06:26:29 -04:00
}
else if ( Collider . CollisionShape . IsBox ( ) )
{
2023-03-27 08:22:19 -04:00
DebugContext . Category . AddShape ( FGameplayDebuggerShape : : MakeBox ( Collider . Location , Collider . Rotation . Rotator ( ) , Collider . CollisionShape . GetExtent ( ) , Data . ColliderColor . ToFColor ( /*bSRGB*/ true ) ) ) ;
2023-03-14 06:26:29 -04:00
}
else if ( Collider . CollisionShape . IsSphere ( ) )
{
2023-03-27 08:22:19 -04:00
DebugContext . Category . AddShape ( FGameplayDebuggerShape : : MakePoint ( Collider . Location , Collider . CollisionShape . GetSphereRadius ( ) , Data . ColliderColor . ToFColor ( /*bSRGB*/ true ) ) ) ;
2023-03-14 06:26:29 -04:00
}
}
}
// Tick at the center.
2023-03-27 08:22:19 -04:00
DebugContext . Category . AddShape ( FGameplayDebuggerShape : : MakeSegmentList ( {
2023-03-14 06:26:29 -04:00
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 ) )
{
2023-03-27 08:22:19 -04:00
DebugContext . Category . AddShape ( FGameplayDebuggerShape : : MakeSegment ( Data . MarkerLocation , Data . SlotLocation , 1.0f , Data . MarkerColor . ToFColor ( /*bSRGB*/ true ) ) ) ;
2023-03-14 06:26:29 -04:00
}
}
# endif // WITH_GAMEPLAY_DEBUGGER