You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
#rb none #jira UE-140139 #preflight 624af57b637925b5d3fb9fef [CL 19609424 by Steve Robb in ue5-main branch]
1209 lines
53 KiB
C++
1209 lines
53 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
/**
|
|
*
|
|
*/
|
|
|
|
#include "DrawDebugHelpers.h"
|
|
#include "EngineGlobals.h"
|
|
#include "Engine/Engine.h"
|
|
#include "CanvasItem.h"
|
|
#include "GameFramework/PlayerController.h"
|
|
#include "GameFramework/WorldSettings.h"
|
|
#include "Components/LineBatchComponent.h"
|
|
#include "Engine/Canvas.h"
|
|
#include "GameFramework/HUD.h"
|
|
|
|
#if ENABLE_DRAW_DEBUG
|
|
|
|
ENGINE_API float GServerDrawDebugColorTintStrength = 0.75f;
|
|
ENGINE_API FLinearColor GServerDrawDebugColorTint(0.0f, 0.0f, 0.0f, 1.0f);
|
|
|
|
#if WITH_EDITOR
|
|
|
|
FColor AdjustColorForServer(const FColor InColor)
|
|
{
|
|
if (GServerDrawDebugColorTintStrength > 0.0f)
|
|
{
|
|
return FMath::Lerp(FLinearColor::FromSRGBColor(InColor), GServerDrawDebugColorTint, GServerDrawDebugColorTintStrength).ToFColor(/*bSRGB=*/ true);
|
|
}
|
|
else
|
|
{
|
|
return InColor;
|
|
}
|
|
}
|
|
|
|
bool CanDrawServerDebugInContext(const FWorldContext& WorldContext)
|
|
{
|
|
return
|
|
(WorldContext.WorldType == EWorldType::PIE) &&
|
|
(WorldContext.World() != nullptr) &&
|
|
(WorldContext.World()->GetNetMode() == NM_Client) &&
|
|
(WorldContext.GameViewport != nullptr) &&
|
|
(WorldContext.GameViewport->EngineShowFlags.ServerDrawDebug);
|
|
}
|
|
|
|
#define UE_DRAW_SERVER_DEBUG_ON_EACH_CLIENT(FunctionName, ...) \
|
|
if (GIsEditor) \
|
|
{ \
|
|
for (const FWorldContext& WorldContext : GEngine->GetWorldContexts()) \
|
|
{ \
|
|
if (CanDrawServerDebugInContext(WorldContext)) \
|
|
{ \
|
|
FunctionName(WorldContext.World(), __VA_ARGS__); \
|
|
} \
|
|
} \
|
|
}
|
|
|
|
#else
|
|
|
|
#define UE_DRAW_SERVER_DEBUG_ON_EACH_CLIENT(FunctionName, ...)
|
|
|
|
#endif
|
|
|
|
|
|
void FlushPersistentDebugLines( const UWorld* InWorld )
|
|
{
|
|
if(InWorld && InWorld->PersistentLineBatcher)
|
|
{
|
|
InWorld->PersistentLineBatcher->Flush();
|
|
}
|
|
}
|
|
|
|
ULineBatchComponent* GetDebugLineBatcher( const UWorld* InWorld, bool bPersistentLines, float LifeTime, bool bDepthIsForeground )
|
|
{
|
|
return (InWorld ? (bDepthIsForeground ? InWorld->ForegroundLineBatcher : (( bPersistentLines || (LifeTime > 0.f) ) ? InWorld->PersistentLineBatcher : InWorld->LineBatcher)) : nullptr);
|
|
}
|
|
|
|
static float GetDebugLineLifeTime(ULineBatchComponent* LineBatcher, float LifeTime, bool bPersistent)
|
|
{
|
|
return bPersistent ? -1.0f : ((LifeTime > 0.f) ? LifeTime : LineBatcher->DefaultLifeTime);
|
|
}
|
|
|
|
void DrawDebugLine(const UWorld* InWorld, FVector const& LineStart, FVector const& LineEnd, FColor const& Color, bool bPersistentLines, float LifeTime, uint8 DepthPriority, float Thickness)
|
|
{
|
|
if (GEngine->GetNetMode(InWorld) != NM_DedicatedServer)
|
|
{
|
|
// this means foreground lines can't be persistent
|
|
if (ULineBatchComponent* const LineBatcher = GetDebugLineBatcher(InWorld, bPersistentLines, LifeTime, (DepthPriority == SDPG_Foreground)))
|
|
{
|
|
float const LineLifeTime = GetDebugLineLifeTime(LineBatcher, LifeTime, bPersistentLines);
|
|
LineBatcher->DrawLine(LineStart, LineEnd, Color, DepthPriority, Thickness, LineLifeTime);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
UE_DRAW_SERVER_DEBUG_ON_EACH_CLIENT(DrawDebugLine, LineStart, LineEnd, AdjustColorForServer(Color), bPersistentLines, LifeTime, DepthPriority, Thickness);
|
|
}
|
|
}
|
|
|
|
void DrawDebugPoint(const UWorld* InWorld, FVector const& Position, float Size, FColor const& Color, bool bPersistentLines, float LifeTime, uint8 DepthPriority)
|
|
{
|
|
if (GEngine->GetNetMode(InWorld) != NM_DedicatedServer)
|
|
{
|
|
// this means foreground lines can't be persistent
|
|
if (ULineBatchComponent* const LineBatcher = GetDebugLineBatcher(InWorld, bPersistentLines, LifeTime, (DepthPriority == SDPG_Foreground)))
|
|
{
|
|
const float PointLifeTime = GetDebugLineLifeTime(LineBatcher, LifeTime, bPersistentLines);
|
|
LineBatcher->DrawPoint(Position, Color.ReinterpretAsLinear(), Size, DepthPriority, PointLifeTime);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
UE_DRAW_SERVER_DEBUG_ON_EACH_CLIENT(DrawDebugPoint, Position, Size, AdjustColorForServer(Color), bPersistentLines, LifeTime, DepthPriority);
|
|
}
|
|
}
|
|
|
|
void DrawDebugDirectionalArrow(const UWorld* InWorld, FVector const& LineStart, FVector const& LineEnd, float ArrowSize, FColor const& Color, bool bPersistentLines, float LifeTime, uint8 DepthPriority, float Thickness)
|
|
{
|
|
// no debug line drawing on dedicated server
|
|
if (GEngine->GetNetMode(InWorld) != NM_DedicatedServer)
|
|
{
|
|
if (ArrowSize <= 0)
|
|
{
|
|
ArrowSize = 10.f;
|
|
}
|
|
|
|
DrawDebugLine(InWorld, LineStart, LineEnd, Color, bPersistentLines, LifeTime, DepthPriority, Thickness);
|
|
|
|
FVector Dir = (LineEnd-LineStart);
|
|
Dir.Normalize();
|
|
FVector Up(0, 0, 1);
|
|
FVector Right = Dir ^ Up;
|
|
if (!Right.IsNormalized())
|
|
{
|
|
Dir.FindBestAxisVectors(Up, Right);
|
|
}
|
|
FVector Origin = FVector::ZeroVector;
|
|
FMatrix TM;
|
|
// get matrix with dir/right/up
|
|
TM.SetAxes(&Dir, &Right, &Up, &Origin);
|
|
|
|
// since dir is x direction, my arrow will be pointing +y, -x and -y, -x
|
|
float ArrowSqrt = FMath::Sqrt(ArrowSize);
|
|
FVector ArrowPos;
|
|
DrawDebugLine(InWorld, LineEnd, LineEnd + TM.TransformPosition(FVector(-ArrowSqrt, ArrowSqrt, 0)), Color, bPersistentLines, LifeTime, DepthPriority, Thickness);
|
|
DrawDebugLine(InWorld, LineEnd, LineEnd + TM.TransformPosition(FVector(-ArrowSqrt, -ArrowSqrt, 0)), Color, bPersistentLines, LifeTime, DepthPriority, Thickness);
|
|
}
|
|
else
|
|
{
|
|
UE_DRAW_SERVER_DEBUG_ON_EACH_CLIENT(DrawDebugDirectionalArrow, LineStart, LineEnd, ArrowSize, AdjustColorForServer(Color), bPersistentLines, LifeTime, DepthPriority, Thickness);
|
|
}
|
|
}
|
|
|
|
void DrawDebugBox(const UWorld* InWorld, FVector const& Center, FVector const& Box, FColor const& Color, bool bPersistentLines, float LifeTime, uint8 DepthPriority, float Thickness)
|
|
{
|
|
// no debug line drawing on dedicated server
|
|
if (GEngine->GetNetMode(InWorld) != NM_DedicatedServer)
|
|
{
|
|
// this means foreground lines can't be persistent
|
|
if (ULineBatchComponent* const LineBatcher = GetDebugLineBatcher(InWorld, bPersistentLines, LifeTime, (DepthPriority == SDPG_Foreground)))
|
|
{
|
|
float LineLifeTime = GetDebugLineLifeTime(LineBatcher, LifeTime, bPersistentLines);
|
|
|
|
LineBatcher->DrawLine(Center + FVector( Box.X, Box.Y, Box.Z), Center + FVector( Box.X, -Box.Y, Box.Z), Color, DepthPriority, Thickness, LineLifeTime);
|
|
LineBatcher->DrawLine(Center + FVector( Box.X, -Box.Y, Box.Z), Center + FVector(-Box.X, -Box.Y, Box.Z), Color, DepthPriority, Thickness, LineLifeTime);
|
|
LineBatcher->DrawLine(Center + FVector(-Box.X, -Box.Y, Box.Z), Center + FVector(-Box.X, Box.Y, Box.Z), Color, DepthPriority, Thickness, LineLifeTime);
|
|
LineBatcher->DrawLine(Center + FVector(-Box.X, Box.Y, Box.Z), Center + FVector( Box.X, Box.Y, Box.Z), Color, DepthPriority, Thickness, LineLifeTime);
|
|
|
|
LineBatcher->DrawLine(Center + FVector( Box.X, Box.Y, -Box.Z), Center + FVector( Box.X, -Box.Y, -Box.Z), Color, DepthPriority, Thickness, LineLifeTime);
|
|
LineBatcher->DrawLine(Center + FVector( Box.X, -Box.Y, -Box.Z), Center + FVector(-Box.X, -Box.Y, -Box.Z), Color, DepthPriority, Thickness, LineLifeTime);
|
|
LineBatcher->DrawLine(Center + FVector(-Box.X, -Box.Y, -Box.Z), Center + FVector(-Box.X, Box.Y, -Box.Z), Color, DepthPriority, Thickness, LineLifeTime);
|
|
LineBatcher->DrawLine(Center + FVector(-Box.X, Box.Y, -Box.Z), Center + FVector( Box.X, Box.Y, -Box.Z), Color, DepthPriority, Thickness, LineLifeTime);
|
|
|
|
LineBatcher->DrawLine(Center + FVector( Box.X, Box.Y, Box.Z), Center + FVector( Box.X, Box.Y, -Box.Z), Color, DepthPriority, Thickness, LineLifeTime);
|
|
LineBatcher->DrawLine(Center + FVector( Box.X, -Box.Y, Box.Z), Center + FVector( Box.X, -Box.Y, -Box.Z), Color, DepthPriority, Thickness, LineLifeTime);
|
|
LineBatcher->DrawLine(Center + FVector(-Box.X, -Box.Y, Box.Z), Center + FVector(-Box.X, -Box.Y, -Box.Z), Color, DepthPriority, Thickness, LineLifeTime);
|
|
LineBatcher->DrawLine(Center + FVector(-Box.X, Box.Y, Box.Z), Center + FVector(-Box.X, Box.Y, -Box.Z), Color, DepthPriority, Thickness, LineLifeTime);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
UE_DRAW_SERVER_DEBUG_ON_EACH_CLIENT(DrawDebugBox, Center, Box, AdjustColorForServer(Color), bPersistentLines, LifeTime, DepthPriority, Thickness);
|
|
}
|
|
}
|
|
|
|
void DrawDebugBox(const UWorld* InWorld, FVector const& Center, FVector const& Box, const FQuat& Rotation, FColor const& Color, bool bPersistentLines, float LifeTime, uint8 DepthPriority, float Thickness)
|
|
{
|
|
// no debug line drawing on dedicated server
|
|
if (GEngine->GetNetMode(InWorld) != NM_DedicatedServer)
|
|
{
|
|
// this means foreground lines can't be persistent
|
|
if (ULineBatchComponent* const LineBatcher = GetDebugLineBatcher(InWorld, bPersistentLines, LifeTime, (DepthPriority == SDPG_Foreground)))
|
|
{
|
|
float const LineLifeTime = GetDebugLineLifeTime(LineBatcher, LifeTime, bPersistentLines);
|
|
TArray<struct FBatchedLine> Lines;
|
|
|
|
FTransform const Transform(Rotation);
|
|
FVector Start = Transform.TransformPosition(FVector( Box.X, Box.Y, Box.Z));
|
|
FVector End = Transform.TransformPosition(FVector( Box.X, -Box.Y, Box.Z));
|
|
new(Lines) FBatchedLine(Center + Start, Center + End, Color, LineLifeTime, Thickness, DepthPriority);
|
|
|
|
Start = Transform.TransformPosition(FVector( Box.X, -Box.Y, Box.Z));
|
|
End = Transform.TransformPosition(FVector(-Box.X, -Box.Y, Box.Z));
|
|
new(Lines) FBatchedLine(Center + Start, Center + End, Color, LineLifeTime, Thickness, DepthPriority);
|
|
|
|
Start = Transform.TransformPosition(FVector(-Box.X, -Box.Y, Box.Z));
|
|
End = Transform.TransformPosition(FVector(-Box.X, Box.Y, Box.Z));
|
|
new(Lines) FBatchedLine(Center + Start, Center + End, Color, LineLifeTime, Thickness, DepthPriority);
|
|
|
|
Start = Transform.TransformPosition(FVector(-Box.X, Box.Y, Box.Z));
|
|
End = Transform.TransformPosition(FVector( Box.X, Box.Y, Box.Z));
|
|
new(Lines) FBatchedLine(Center + Start, Center + End, Color, LineLifeTime, Thickness, DepthPriority);
|
|
|
|
Start = Transform.TransformPosition(FVector( Box.X, Box.Y, -Box.Z));
|
|
End = Transform.TransformPosition(FVector( Box.X, -Box.Y, -Box.Z));
|
|
new(Lines) FBatchedLine(Center + Start, Center + End, Color, LineLifeTime, Thickness, DepthPriority);
|
|
|
|
Start = Transform.TransformPosition(FVector( Box.X, -Box.Y, -Box.Z));
|
|
End = Transform.TransformPosition(FVector(-Box.X, -Box.Y, -Box.Z));
|
|
new(Lines) FBatchedLine(Center + Start, Center + End, Color, LineLifeTime, Thickness, DepthPriority);
|
|
|
|
Start = Transform.TransformPosition(FVector(-Box.X, -Box.Y, -Box.Z));
|
|
End = Transform.TransformPosition(FVector(-Box.X, Box.Y, -Box.Z));
|
|
new(Lines) FBatchedLine(Center + Start, Center + End, Color, LineLifeTime, Thickness, DepthPriority);
|
|
|
|
Start = Transform.TransformPosition(FVector(-Box.X, Box.Y, -Box.Z));
|
|
End = Transform.TransformPosition(FVector( Box.X, Box.Y, -Box.Z));
|
|
new(Lines )FBatchedLine(Center + Start, Center + End, Color, LineLifeTime, Thickness, DepthPriority);
|
|
|
|
Start = Transform.TransformPosition(FVector( Box.X, Box.Y, Box.Z));
|
|
End = Transform.TransformPosition(FVector( Box.X, Box.Y, -Box.Z));
|
|
new(Lines) FBatchedLine(Center + Start, Center + End, Color, LineLifeTime, Thickness, DepthPriority);
|
|
|
|
Start = Transform.TransformPosition(FVector( Box.X, -Box.Y, Box.Z));
|
|
End = Transform.TransformPosition(FVector( Box.X, -Box.Y, -Box.Z));
|
|
new(Lines) FBatchedLine(Center + Start, Center + End, Color, LineLifeTime, Thickness, DepthPriority);
|
|
|
|
Start = Transform.TransformPosition(FVector(-Box.X, -Box.Y, Box.Z));
|
|
End = Transform.TransformPosition(FVector(-Box.X, -Box.Y, -Box.Z));
|
|
new(Lines) FBatchedLine(Center + Start, Center + End, Color, LineLifeTime, Thickness, DepthPriority);
|
|
|
|
Start = Transform.TransformPosition(FVector(-Box.X, Box.Y, Box.Z));
|
|
End = Transform.TransformPosition(FVector(-Box.X, Box.Y, -Box.Z));
|
|
new(Lines) FBatchedLine(Center + Start, Center + End, Color, LineLifeTime, Thickness, DepthPriority);
|
|
|
|
LineBatcher->DrawLines(Lines);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
UE_DRAW_SERVER_DEBUG_ON_EACH_CLIENT(DrawDebugBox, Center, Box, Rotation, AdjustColorForServer(Color), bPersistentLines, LifeTime, DepthPriority, Thickness);
|
|
}
|
|
}
|
|
|
|
|
|
void DrawDebugMesh(const UWorld* InWorld, TArray<FVector> const& Verts, TArray<int32> const& Indices, FColor const& Color, bool bPersistent, float LifeTime, uint8 DepthPriority)
|
|
{
|
|
// no debug line drawing on dedicated server
|
|
if (GEngine->GetNetMode(InWorld) != NM_DedicatedServer)
|
|
{
|
|
if (ULineBatchComponent* const LineBatcher = GetDebugLineBatcher(InWorld, bPersistent, LifeTime, false))
|
|
{
|
|
float const ActualLifetime = GetDebugLineLifeTime(LineBatcher, LifeTime, bPersistent);
|
|
LineBatcher->DrawMesh(Verts, Indices, Color, DepthPriority, ActualLifetime);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
UE_DRAW_SERVER_DEBUG_ON_EACH_CLIENT(DrawDebugMesh, Verts, Indices, AdjustColorForServer(Color), bPersistent, LifeTime, DepthPriority);
|
|
}
|
|
}
|
|
|
|
void DrawDebugSolidBox(const UWorld* InWorld, FBox const& Box, FColor const& Color, const FTransform& Transform, bool bPersistent, float LifeTime, uint8 DepthPriority)
|
|
{
|
|
// no debug line drawing on dedicated server
|
|
if (GEngine->GetNetMode(InWorld) != NM_DedicatedServer)
|
|
{
|
|
if (ULineBatchComponent* const LineBatcher = GetDebugLineBatcher(InWorld, bPersistent, LifeTime, false))
|
|
{
|
|
float const ActualLifetime = GetDebugLineLifeTime(LineBatcher, LifeTime, bPersistent);
|
|
LineBatcher->DrawSolidBox(Box, Transform, Color, DepthPriority, ActualLifetime);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
UE_DRAW_SERVER_DEBUG_ON_EACH_CLIENT(DrawDebugSolidBox, Box, AdjustColorForServer(Color), Transform, bPersistent, LifeTime, DepthPriority);
|
|
}
|
|
}
|
|
|
|
void DrawDebugSolidBox(const UWorld* InWorld, FVector const& Center, FVector const& Extent, FColor const& Color, bool bPersistent, float LifeTime, uint8 DepthPriority)
|
|
{ // No Rotation, so just use identity transform and build the box in the right place!
|
|
FBox Box = FBox::BuildAABB(Center, Extent);
|
|
|
|
DrawDebugSolidBox(InWorld, Box, Color, FTransform::Identity, bPersistent, LifeTime, DepthPriority);
|
|
}
|
|
|
|
void DrawDebugSolidBox(const UWorld* InWorld, FVector const& Center, FVector const& Extent, FQuat const& Rotation, FColor const& Color, bool bPersistent, float LifeTime, uint8 DepthPriority)
|
|
{
|
|
FTransform Transform(Rotation, Center, FVector(1.0f, 1.0f, 1.0f)); // Build transform from Rotation, Center with uniform scale of 1.0.
|
|
FBox Box = FBox::BuildAABB(FVector::ZeroVector, Extent); // The Transform handles the Center location, so this box needs to be centered on origin.
|
|
|
|
DrawDebugSolidBox(InWorld, Box, Color, Transform, bPersistent, LifeTime, DepthPriority);
|
|
}
|
|
|
|
/** Loc is an anchor point in the world to guide which part of the infinite plane to draw. */
|
|
void DrawDebugSolidPlane(const UWorld* InWorld, FPlane const& P, FVector const& Loc, float Size, FColor const& Color, bool bPersistent, float LifeTime, uint8 DepthPriority)
|
|
{
|
|
DrawDebugSolidPlane(InWorld, P, Loc, FVector2D(Size, Size), Color, bPersistent, LifeTime, DepthPriority);
|
|
}
|
|
|
|
ENGINE_API void DrawDebugSolidPlane(const UWorld* InWorld, FPlane const& P, FVector const& Loc, FVector2D const& Extents, FColor const& Color, bool bPersistent/*=false*/, float LifeTime/*=-1*/, uint8 DepthPriority /*= 0*/)
|
|
{
|
|
// no debug line drawing on dedicated server
|
|
if(GEngine->GetNetMode(InWorld) != NM_DedicatedServer)
|
|
{
|
|
FVector const ClosestPtOnPlane = Loc - P.PlaneDot(Loc) * P;
|
|
|
|
FVector U, V;
|
|
P.FindBestAxisVectors(U, V);
|
|
U *= Extents.Y;
|
|
V *= Extents.X;
|
|
|
|
TArray<FVector> Verts;
|
|
Verts.AddUninitialized(4);
|
|
Verts[0] = ClosestPtOnPlane + U + V;
|
|
Verts[1] = ClosestPtOnPlane - U + V;
|
|
Verts[2] = ClosestPtOnPlane + U - V;
|
|
Verts[3] = ClosestPtOnPlane - U - V;
|
|
|
|
TArray<int32> Indices;
|
|
Indices.AddUninitialized(6);
|
|
Indices[0] = 0; Indices[1] = 2; Indices[2] = 1;
|
|
Indices[3] = 1; Indices[4] = 2; Indices[5] = 3;
|
|
|
|
// plane quad
|
|
DrawDebugMesh(InWorld, Verts, Indices, Color, bPersistent, LifeTime, DepthPriority);
|
|
|
|
// arrow indicating normal
|
|
DrawDebugDirectionalArrow(InWorld, ClosestPtOnPlane, ClosestPtOnPlane + P * 16.f, 8.f, FColor::White, bPersistent, LifeTime, DepthPriority);
|
|
}
|
|
else
|
|
{
|
|
UE_DRAW_SERVER_DEBUG_ON_EACH_CLIENT(DrawDebugSolidPlane, P, Loc, Extents, AdjustColorForServer(Color), bPersistent, LifeTime, DepthPriority);
|
|
}
|
|
}
|
|
|
|
void DrawDebugCoordinateSystem(const UWorld* InWorld, FVector const& AxisLoc, FRotator const& AxisRot, float Scale, bool bPersistentLines, float LifeTime, uint8 DepthPriority, float Thickness)
|
|
{
|
|
// no debug line drawing on dedicated server
|
|
if (GEngine->GetNetMode(InWorld) != NM_DedicatedServer)
|
|
{
|
|
FRotationMatrix R(AxisRot);
|
|
FVector const X = R.GetScaledAxis( EAxis::X );
|
|
FVector const Y = R.GetScaledAxis( EAxis::Y );
|
|
FVector const Z = R.GetScaledAxis( EAxis::Z );
|
|
|
|
// this means foreground lines can't be persistent
|
|
if (ULineBatchComponent* const LineBatcher = GetDebugLineBatcher(InWorld, bPersistentLines, LifeTime, (DepthPriority == SDPG_Foreground)))
|
|
{
|
|
const float LineLifeTime = GetDebugLineLifeTime(LineBatcher, LifeTime, bPersistentLines);
|
|
LineBatcher->DrawLine(AxisLoc, AxisLoc + X*Scale, FColor::Red, DepthPriority, Thickness, LineLifeTime );
|
|
LineBatcher->DrawLine(AxisLoc, AxisLoc + Y*Scale, FColor::Green, DepthPriority, Thickness, LineLifeTime );
|
|
LineBatcher->DrawLine(AxisLoc, AxisLoc + Z*Scale, FColor::Blue, DepthPriority, Thickness, LineLifeTime );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
UE_DRAW_SERVER_DEBUG_ON_EACH_CLIENT(DrawDebugCoordinateSystem, AxisLoc, AxisRot, Scale, bPersistentLines, LifeTime, DepthPriority, Thickness);
|
|
}
|
|
}
|
|
|
|
ENGINE_API void DrawDebugCrosshairs(const UWorld* InWorld, FVector const& AxisLoc, FRotator const& AxisRot, float Scale, const FColor& Color, bool bPersistentLines, float LifeTime, uint8 DepthPriority)
|
|
{
|
|
// no debug line drawing on dedicated server
|
|
if (GEngine->GetNetMode(InWorld) != NM_DedicatedServer)
|
|
{
|
|
FRotationMatrix R(AxisRot);
|
|
FVector const X = 0.5f * R.GetScaledAxis(EAxis::X);
|
|
FVector const Y = 0.5f * R.GetScaledAxis(EAxis::Y);
|
|
FVector const Z = 0.5f * R.GetScaledAxis(EAxis::Z);
|
|
|
|
// this means foreground lines can't be persistent
|
|
if (ULineBatchComponent* const LineBatcher = GetDebugLineBatcher(InWorld, bPersistentLines, LifeTime, (DepthPriority == SDPG_Foreground)))
|
|
{
|
|
const float LineLifeTime = GetDebugLineLifeTime(LineBatcher, LifeTime, bPersistentLines);
|
|
LineBatcher->DrawLine(AxisLoc - X*Scale, AxisLoc + X*Scale, Color, DepthPriority, 0.f, LineLifeTime);
|
|
LineBatcher->DrawLine(AxisLoc - Y*Scale, AxisLoc + Y*Scale, Color, DepthPriority, 0.f, LineLifeTime);
|
|
LineBatcher->DrawLine(AxisLoc - Z*Scale, AxisLoc + Z*Scale, Color, DepthPriority, 0.f, LineLifeTime);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
UE_DRAW_SERVER_DEBUG_ON_EACH_CLIENT(DrawDebugCrosshairs, AxisLoc, AxisRot, Scale, AdjustColorForServer(Color), bPersistentLines, LifeTime, DepthPriority);
|
|
}
|
|
}
|
|
|
|
|
|
static void InternalDrawDebugCircle(const UWorld* InWorld, const FMatrix& TransformMatrix, float Radius, int32 Segments, const FColor& Color, bool bPersistentLines, float LifeTime, uint8 DepthPriority, float Thickness = 0.f)
|
|
{
|
|
if (ULineBatchComponent* const LineBatcher = GetDebugLineBatcher(InWorld, bPersistentLines, LifeTime, (DepthPriority == SDPG_Foreground)))
|
|
{
|
|
const float LineLifeTime = GetDebugLineLifeTime(LineBatcher, LifeTime, bPersistentLines);
|
|
|
|
// Need at least 4 segments
|
|
Segments = FMath::Max(Segments, 4);
|
|
const float AngleStep = 2.f * UE_PI / float(Segments);
|
|
|
|
const FVector Center = TransformMatrix.GetOrigin();
|
|
const FVector AxisY = TransformMatrix.GetScaledAxis(EAxis::Y);
|
|
const FVector AxisZ = TransformMatrix.GetScaledAxis(EAxis::Z);
|
|
|
|
TArray<FBatchedLine> Lines;
|
|
Lines.Empty(Segments);
|
|
|
|
float Angle = 0.f;
|
|
while (Segments--)
|
|
{
|
|
const FVector Vertex1 = Center + Radius * (AxisY * FMath::Cos(Angle) + AxisZ * FMath::Sin(Angle));
|
|
Angle += AngleStep;
|
|
const FVector Vertex2 = Center + Radius * (AxisY * FMath::Cos(Angle) + AxisZ * FMath::Sin(Angle));
|
|
Lines.Add(FBatchedLine(Vertex1, Vertex2, Color, LineLifeTime, Thickness, DepthPriority));
|
|
}
|
|
LineBatcher->DrawLines(Lines);
|
|
}
|
|
}
|
|
|
|
void DrawDebugCircle(const UWorld* InWorld, const FMatrix& TransformMatrix, float Radius, int32 Segments, const FColor& Color, bool bPersistentLines, float LifeTime, uint8 DepthPriority, float Thickness, bool bDrawAxis)
|
|
{
|
|
// no debug line drawing on dedicated server
|
|
if (GEngine->GetNetMode(InWorld) != NM_DedicatedServer)
|
|
{
|
|
if (ULineBatchComponent* const LineBatcher = GetDebugLineBatcher(InWorld, bPersistentLines, LifeTime, (DepthPriority == SDPG_Foreground)))
|
|
{
|
|
const float LineLifeTime = GetDebugLineLifeTime(LineBatcher, LifeTime, bPersistentLines);
|
|
|
|
// Need at least 4 segments
|
|
Segments = FMath::Max((Segments - 2) / 2, 4);
|
|
InternalDrawDebugCircle(InWorld, TransformMatrix, Radius, Segments, Color, bPersistentLines, LifeTime, DepthPriority, Thickness);
|
|
|
|
if (bDrawAxis)
|
|
{
|
|
const FVector Center = TransformMatrix.GetOrigin();
|
|
const FVector AxisY = TransformMatrix.GetScaledAxis( EAxis::Y );
|
|
const FVector AxisZ = TransformMatrix.GetScaledAxis( EAxis::Z );
|
|
|
|
TArray<FBatchedLine> Lines;
|
|
Lines.Empty(2);
|
|
Lines.Add(FBatchedLine(Center - Radius * AxisY, Center + Radius * AxisY, Color, LineLifeTime, Thickness, DepthPriority));
|
|
Lines.Add(FBatchedLine(Center - Radius * AxisZ, Center + Radius * AxisZ, Color, LineLifeTime, Thickness, DepthPriority));
|
|
LineBatcher->DrawLines(Lines);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
UE_DRAW_SERVER_DEBUG_ON_EACH_CLIENT(DrawDebugCircle, TransformMatrix, Radius, Segments, AdjustColorForServer(Color), bPersistentLines, LifeTime, DepthPriority, Thickness, bDrawAxis);
|
|
}
|
|
}
|
|
|
|
void DrawDebugCircle(const UWorld* InWorld, FVector Center, float Radius, int32 Segments, const FColor& Color, bool PersistentLines, float LifeTime, uint8 DepthPriority, float Thickness, FVector YAxis, FVector ZAxis, bool bDrawAxis)
|
|
{
|
|
FMatrix TM;
|
|
TM.SetOrigin(Center);
|
|
TM.SetAxis(0, FVector(1,0,0));
|
|
TM.SetAxis(1, YAxis);
|
|
TM.SetAxis(2, ZAxis);
|
|
|
|
DrawDebugCircle(
|
|
InWorld,
|
|
TM,
|
|
Radius,
|
|
Segments,
|
|
Color,
|
|
PersistentLines,
|
|
LifeTime,
|
|
DepthPriority,
|
|
Thickness,
|
|
bDrawAxis
|
|
);
|
|
}
|
|
|
|
void DrawDebugCircleArc(const UWorld* InWorld, const FVector& Center, float Radius, const FVector& Direction, float AngleWidth, int32 Segments, const FColor& Color, bool PersistentLines, float LifeTime, uint8 DepthPriority, float Thickness)
|
|
{
|
|
if (GEngine->GetNetMode(InWorld) != NM_DedicatedServer)
|
|
{
|
|
if (ULineBatchComponent* const LineBatcher = GetDebugLineBatcher(InWorld, PersistentLines, LifeTime, (DepthPriority == SDPG_Foreground)))
|
|
{
|
|
const float LineLifeTime = GetDebugLineLifeTime(LineBatcher, LifeTime, PersistentLines);
|
|
|
|
// Need at least 4 segments
|
|
Segments = FMath::Max(Segments, 4);
|
|
const float AngleStep = AngleWidth / float(Segments) * 2.f;
|
|
|
|
FVector AxisY, AxisZ;
|
|
FVector DirectionNorm = Direction.GetSafeNormal();
|
|
DirectionNorm.FindBestAxisVectors(AxisZ, AxisY);
|
|
|
|
TArray<FBatchedLine> Lines;
|
|
Lines.Empty(Segments);
|
|
float Angle = -AngleWidth;
|
|
FVector PrevVertex = Center + Radius * (AxisY * -FMath::Sin(Angle) + DirectionNorm * FMath::Cos(Angle));
|
|
while (Segments--)
|
|
{
|
|
Angle += AngleStep;
|
|
FVector NextVertex = Center + Radius * (AxisY * -FMath::Sin(Angle) + DirectionNorm * FMath::Cos(Angle));
|
|
Lines.Emplace(FBatchedLine(PrevVertex, NextVertex, Color, LineLifeTime, Thickness, DepthPriority));
|
|
PrevVertex = NextVertex;
|
|
}
|
|
|
|
LineBatcher->DrawLines(Lines);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
UE_DRAW_SERVER_DEBUG_ON_EACH_CLIENT(DrawDebugCircleArc, Center, Radius, Direction, AngleWidth, Segments, AdjustColorForServer(Color), PersistentLines, LifeTime, DepthPriority, Thickness);
|
|
}
|
|
|
|
}
|
|
|
|
void DrawDebug2DDonut(const UWorld* InWorld, const FMatrix& TransformMatrix, float InnerRadius, float OuterRadius, int32 Segments, const FColor& Color, bool bPersistentLines, float LifeTime, uint8 DepthPriority, float Thickness)
|
|
{
|
|
// no debug line drawing on dedicated server
|
|
if (GEngine->GetNetMode(InWorld) != NM_DedicatedServer)
|
|
{
|
|
if (ULineBatchComponent* const LineBatcher = GetDebugLineBatcher(InWorld, bPersistentLines, LifeTime, (DepthPriority == SDPG_Foreground)))
|
|
{
|
|
const float LineLifeTime = GetDebugLineLifeTime(LineBatcher, LifeTime, bPersistentLines);
|
|
|
|
// Need at least 4 segments
|
|
Segments = FMath::Max((Segments - 4) / 2, 4);
|
|
InternalDrawDebugCircle(InWorld, TransformMatrix, InnerRadius, Segments, Color, bPersistentLines, LifeTime, DepthPriority, Thickness);
|
|
InternalDrawDebugCircle(InWorld, TransformMatrix, OuterRadius, Segments, Color, bPersistentLines, LifeTime, DepthPriority, Thickness );
|
|
|
|
const FVector Center = TransformMatrix.GetOrigin();
|
|
const FVector AxisY = TransformMatrix.GetScaledAxis( EAxis::Y );
|
|
const FVector AxisZ = TransformMatrix.GetScaledAxis( EAxis::Z );
|
|
|
|
TArray<FBatchedLine> Lines;
|
|
Lines.Empty(4);
|
|
Lines.Add(FBatchedLine(Center - OuterRadius * AxisY, Center - InnerRadius * AxisY, Color, LineLifeTime, Thickness, DepthPriority));
|
|
Lines.Add(FBatchedLine(Center + OuterRadius * AxisY, Center + InnerRadius * AxisY, Color, LineLifeTime, Thickness, DepthPriority));
|
|
Lines.Add(FBatchedLine(Center - OuterRadius * AxisZ, Center - InnerRadius * AxisZ, Color, LineLifeTime, Thickness, DepthPriority));
|
|
Lines.Add(FBatchedLine(Center + OuterRadius * AxisZ, Center + InnerRadius * AxisZ, Color, LineLifeTime, Thickness, DepthPriority));
|
|
LineBatcher->DrawLines(Lines);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
UE_DRAW_SERVER_DEBUG_ON_EACH_CLIENT(DrawDebug2DDonut, TransformMatrix, InnerRadius, OuterRadius, Segments, AdjustColorForServer(Color), bPersistentLines, LifeTime, DepthPriority, Thickness);
|
|
}
|
|
}
|
|
|
|
void DrawDebugSphere(const UWorld* InWorld, FVector const& Center, float Radius, int32 Segments, FColor const& Color, bool bPersistentLines, float LifeTime, uint8 DepthPriority, float Thickness)
|
|
{
|
|
// no debug line drawing on dedicated server
|
|
if (GEngine->GetNetMode(InWorld) != NM_DedicatedServer)
|
|
{
|
|
// this means foreground lines can't be persistent
|
|
if (ULineBatchComponent* const LineBatcher = GetDebugLineBatcher(InWorld, bPersistentLines, LifeTime, (DepthPriority == SDPG_Foreground)))
|
|
{
|
|
float LineLifeTime = GetDebugLineLifeTime(LineBatcher, LifeTime, bPersistentLines);
|
|
|
|
// Need at least 4 segments
|
|
Segments = FMath::Max(Segments, 4);
|
|
|
|
FVector Vertex1, Vertex2, Vertex3, Vertex4;
|
|
const float AngleInc = 2.f * UE_PI / float(Segments);
|
|
int32 NumSegmentsY = Segments;
|
|
float Latitude = AngleInc;
|
|
int32 NumSegmentsX;
|
|
float Longitude;
|
|
float SinY1 = 0.0f, CosY1 = 1.0f, SinY2, CosY2;
|
|
float SinX, CosX;
|
|
|
|
TArray<FBatchedLine> Lines;
|
|
Lines.Empty(NumSegmentsY * Segments * 2);
|
|
while (NumSegmentsY--)
|
|
{
|
|
SinY2 = FMath::Sin(Latitude);
|
|
CosY2 = FMath::Cos(Latitude);
|
|
|
|
Vertex1 = FVector(SinY1, 0.0f, CosY1) * Radius + Center;
|
|
Vertex3 = FVector(SinY2, 0.0f, CosY2) * Radius + Center;
|
|
Longitude = AngleInc;
|
|
|
|
NumSegmentsX = Segments;
|
|
while (NumSegmentsX--)
|
|
{
|
|
SinX = FMath::Sin(Longitude);
|
|
CosX = FMath::Cos(Longitude);
|
|
|
|
Vertex2 = FVector((CosX * SinY1), (SinX * SinY1), CosY1) * Radius + Center;
|
|
Vertex4 = FVector((CosX * SinY2), (SinX * SinY2), CosY2) * Radius + Center;
|
|
|
|
Lines.Add(FBatchedLine(Vertex1, Vertex2, Color, LineLifeTime, Thickness, DepthPriority));
|
|
Lines.Add(FBatchedLine(Vertex1, Vertex3, Color, LineLifeTime, Thickness, DepthPriority));
|
|
|
|
Vertex1 = Vertex2;
|
|
Vertex3 = Vertex4;
|
|
Longitude += AngleInc;
|
|
}
|
|
SinY1 = SinY2;
|
|
CosY1 = CosY2;
|
|
Latitude += AngleInc;
|
|
}
|
|
LineBatcher->DrawLines(Lines);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
UE_DRAW_SERVER_DEBUG_ON_EACH_CLIENT(DrawDebugSphere, Center, Radius, Segments, AdjustColorForServer(Color), bPersistentLines, LifeTime, DepthPriority, Thickness);
|
|
}
|
|
}
|
|
|
|
void DrawDebugCylinder(const UWorld* InWorld, FVector const& Start, FVector const& End, float Radius, int32 Segments, FColor const& Color, bool bPersistentLines, float LifeTime, uint8 DepthPriority, float Thickness)
|
|
{
|
|
// no debug line drawing on dedicated server
|
|
if (GEngine->GetNetMode(InWorld) != NM_DedicatedServer)
|
|
{
|
|
// this means foreground lines can't be persistent
|
|
if (ULineBatchComponent* const LineBatcher = GetDebugLineBatcher(InWorld, bPersistentLines, LifeTime, (DepthPriority == SDPG_Foreground)))
|
|
{
|
|
// Need at least 4 segments
|
|
Segments = FMath::Max(Segments, 4);
|
|
|
|
// Rotate a point around axis to form cylinder segments
|
|
FVector Segment;
|
|
FVector P1, P2, P3, P4;
|
|
const float AngleInc = 360.f / Segments;
|
|
float Angle = AngleInc;
|
|
|
|
// Default for Axis is up
|
|
FVector Axis = (End - Start).GetSafeNormal();
|
|
if( Axis.IsZero() )
|
|
{
|
|
Axis = FVector(0.f, 0.f, 1.f);
|
|
}
|
|
|
|
FVector Perpendicular;
|
|
FVector Dummy;
|
|
|
|
Axis.FindBestAxisVectors(Perpendicular, Dummy);
|
|
|
|
Segment = Perpendicular.RotateAngleAxis(0, Axis) * Radius;
|
|
P1 = Segment + Start;
|
|
P3 = Segment + End;
|
|
|
|
const float LineLifeTime = GetDebugLineLifeTime(LineBatcher, LifeTime, bPersistentLines);
|
|
while( Segments-- )
|
|
{
|
|
Segment = Perpendicular.RotateAngleAxis(Angle, Axis) * Radius;
|
|
P2 = Segment + Start;
|
|
P4 = Segment + End;
|
|
|
|
LineBatcher->DrawLine(P2, P4, Color, DepthPriority, Thickness, LineLifeTime);
|
|
LineBatcher->DrawLine(P1, P2, Color, DepthPriority, Thickness, LineLifeTime);
|
|
LineBatcher->DrawLine(P3, P4, Color, DepthPriority, Thickness, LineLifeTime);
|
|
|
|
P1 = P2;
|
|
P3 = P4;
|
|
Angle += AngleInc;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
UE_DRAW_SERVER_DEBUG_ON_EACH_CLIENT(DrawDebugCylinder, Start, End, Radius, Segments, AdjustColorForServer(Color), bPersistentLines, LifeTime, DepthPriority, Thickness);
|
|
}
|
|
}
|
|
|
|
/** Used by gameplay when defining a cone by a vertical and horizontal dot products. */
|
|
void DrawDebugAltCone(const UWorld* InWorld, FVector const& Origin, FRotator const& Rotation, float Length, float AngleWidth, float AngleHeight, FColor const& DrawColor, bool bPersistentLines, float LifeTime, uint8 DepthPriority, float Thickness)
|
|
{
|
|
if (GEngine->GetNetMode(InWorld) != NM_DedicatedServer)
|
|
{
|
|
// this means foreground lines can't be persistent
|
|
if (ULineBatchComponent* const LineBatcher = GetDebugLineBatcher(InWorld, bPersistentLines, LifeTime, (DepthPriority == SDPG_Foreground)))
|
|
{
|
|
FRotationMatrix const RM(Rotation);
|
|
FVector const AxisX = RM.GetScaledAxis(EAxis::X);
|
|
FVector const AxisY = RM.GetScaledAxis(EAxis::Y);
|
|
FVector const AxisZ = RM.GetScaledAxis(EAxis::Z);
|
|
|
|
float const LineLifeTime = GetDebugLineLifeTime(LineBatcher, LifeTime, bPersistentLines);
|
|
|
|
FVector const EndPoint = Origin + AxisX * Length;
|
|
FVector const Up = FMath::Tan(AngleHeight * 0.5f) * AxisZ * Length;
|
|
FVector const Right = FMath::Tan(AngleWidth * 0.5f) * AxisY * Length;
|
|
FVector const HalfUp = Up * 0.5f;
|
|
FVector const HalfRight = Right * 0.5f;
|
|
|
|
TArray<FBatchedLine> Lines;
|
|
Lines.Empty();
|
|
|
|
FVector A = EndPoint + Up - Right;
|
|
FVector B = EndPoint + Up + Right;
|
|
FVector C = EndPoint - Up + Right;
|
|
FVector D = EndPoint - Up - Right;
|
|
|
|
// Corners
|
|
Lines.Add(FBatchedLine(Origin, A, DrawColor, LineLifeTime, Thickness, DepthPriority));
|
|
Lines.Add(FBatchedLine(Origin, B, DrawColor, LineLifeTime, Thickness, DepthPriority));
|
|
Lines.Add(FBatchedLine(Origin, C, DrawColor, LineLifeTime, Thickness, DepthPriority));
|
|
Lines.Add(FBatchedLine(Origin, D, DrawColor, LineLifeTime, Thickness, DepthPriority));
|
|
|
|
// Further most plane/frame
|
|
Lines.Add(FBatchedLine(A, B, DrawColor, LineLifeTime, Thickness, DepthPriority));
|
|
Lines.Add(FBatchedLine(B, C, DrawColor, LineLifeTime, Thickness, DepthPriority));
|
|
Lines.Add(FBatchedLine(C, D, DrawColor, LineLifeTime, Thickness, DepthPriority));
|
|
Lines.Add(FBatchedLine(D, A, DrawColor, LineLifeTime, Thickness, DepthPriority));
|
|
|
|
// Mid points
|
|
Lines.Add(FBatchedLine(Origin, EndPoint + Up, DrawColor, LineLifeTime, Thickness, DepthPriority));
|
|
Lines.Add(FBatchedLine(Origin, EndPoint - Up, DrawColor, LineLifeTime, Thickness, DepthPriority));
|
|
Lines.Add(FBatchedLine(Origin, EndPoint + Right, DrawColor, LineLifeTime, Thickness, DepthPriority));
|
|
Lines.Add(FBatchedLine(Origin, EndPoint - Right, DrawColor, LineLifeTime, Thickness, DepthPriority));
|
|
|
|
// Inbetween
|
|
Lines.Add(FBatchedLine(Origin, EndPoint + Up - HalfRight, DrawColor, LineLifeTime, Thickness, DepthPriority));
|
|
Lines.Add(FBatchedLine(Origin, EndPoint + Up + HalfRight, DrawColor, LineLifeTime, Thickness, DepthPriority));
|
|
|
|
Lines.Add(FBatchedLine(Origin, EndPoint - Up - HalfRight, DrawColor, LineLifeTime, Thickness, DepthPriority));
|
|
Lines.Add(FBatchedLine(Origin, EndPoint - Up + HalfRight, DrawColor, LineLifeTime, Thickness, DepthPriority));
|
|
|
|
Lines.Add(FBatchedLine(Origin, EndPoint + Right - HalfUp, DrawColor, LineLifeTime, Thickness, DepthPriority));
|
|
Lines.Add(FBatchedLine(Origin, EndPoint + Right + HalfUp, DrawColor, LineLifeTime, Thickness, DepthPriority));
|
|
|
|
Lines.Add(FBatchedLine(Origin, EndPoint - Right - HalfUp, DrawColor, LineLifeTime, Thickness, DepthPriority));
|
|
Lines.Add(FBatchedLine(Origin, EndPoint - Right + HalfUp, DrawColor, LineLifeTime, Thickness, DepthPriority));
|
|
|
|
LineBatcher->DrawLines(Lines);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
UE_DRAW_SERVER_DEBUG_ON_EACH_CLIENT(DrawDebugAltCone, Origin, Rotation, Length, AngleWidth, AngleHeight, AdjustColorForServer(DrawColor), bPersistentLines, LifeTime, DepthPriority, Thickness);
|
|
}
|
|
}
|
|
|
|
void DrawDebugCone(const UWorld* InWorld, FVector const& Origin, FVector const& Direction, float Length, float AngleWidth, float AngleHeight, int32 NumSides, FColor const& DrawColor, bool bPersistentLines, float LifeTime, uint8 DepthPriority, float Thickness)
|
|
{
|
|
// no debug line drawing on dedicated server
|
|
if (GEngine->GetNetMode(InWorld) != NM_DedicatedServer)
|
|
{
|
|
// Need at least 4 sides
|
|
NumSides = FMath::Max(NumSides, 4);
|
|
|
|
const float Angle1 = FMath::Clamp<float>(AngleHeight, (float)UE_KINDA_SMALL_NUMBER, (float)(UE_PI - UE_KINDA_SMALL_NUMBER));
|
|
const float Angle2 = FMath::Clamp<float>(AngleWidth, (float)UE_KINDA_SMALL_NUMBER, (float)(UE_PI - UE_KINDA_SMALL_NUMBER));
|
|
|
|
const float SinX_2 = FMath::Sin(0.5f * Angle1);
|
|
const float SinY_2 = FMath::Sin(0.5f * Angle2);
|
|
|
|
const float SinSqX_2 = SinX_2 * SinX_2;
|
|
const float SinSqY_2 = SinY_2 * SinY_2;
|
|
|
|
const float TanX_2 = FMath::Tan(0.5f * Angle1);
|
|
const float TanY_2 = FMath::Tan(0.5f * Angle2);
|
|
|
|
TArray<FVector> ConeVerts;
|
|
ConeVerts.AddUninitialized(NumSides);
|
|
|
|
for(int32 i = 0; i < NumSides; i++)
|
|
{
|
|
const float Fraction = (float)i/(float)(NumSides);
|
|
const float Thi = 2.f * UE_PI * Fraction;
|
|
const float Phi = FMath::Atan2(FMath::Sin(Thi)*SinY_2, FMath::Cos(Thi)*SinX_2);
|
|
const float SinPhi = FMath::Sin(Phi);
|
|
const float CosPhi = FMath::Cos(Phi);
|
|
const float SinSqPhi = SinPhi*SinPhi;
|
|
const float CosSqPhi = CosPhi*CosPhi;
|
|
|
|
const float RSq = SinSqX_2*SinSqY_2 / (SinSqX_2*SinSqPhi + SinSqY_2*CosSqPhi);
|
|
const float R = FMath::Sqrt(RSq);
|
|
const float Sqr = FMath::Sqrt(1-RSq);
|
|
const float Alpha = R*CosPhi;
|
|
const float Beta = R*SinPhi;
|
|
|
|
ConeVerts[i].X = (1 - 2*RSq);
|
|
ConeVerts[i].Y = 2 * Sqr * Alpha;
|
|
ConeVerts[i].Z = 2 * Sqr * Beta;
|
|
}
|
|
|
|
// Calculate transform for cone.
|
|
FVector YAxis, ZAxis;
|
|
FVector DirectionNorm = Direction.GetSafeNormal();
|
|
DirectionNorm.FindBestAxisVectors(YAxis, ZAxis);
|
|
const FMatrix ConeToWorld = FScaleMatrix(FVector(Length)) * FMatrix(DirectionNorm, YAxis, ZAxis, Origin);
|
|
|
|
// this means foreground lines can't be persistent
|
|
if (ULineBatchComponent* const LineBatcher = GetDebugLineBatcher(InWorld, bPersistentLines, LifeTime, (DepthPriority == SDPG_Foreground)))
|
|
{
|
|
float const LineLifeTime = GetDebugLineLifeTime(LineBatcher, LifeTime, bPersistentLines);
|
|
|
|
TArray<FBatchedLine> Lines;
|
|
Lines.Empty(NumSides);
|
|
|
|
FVector CurrentPoint, PrevPoint, FirstPoint;
|
|
for(int32 i = 0; i < NumSides; i++)
|
|
{
|
|
CurrentPoint = ConeToWorld.TransformPosition(ConeVerts[i]);
|
|
Lines.Add(FBatchedLine(ConeToWorld.GetOrigin(), CurrentPoint, DrawColor, LineLifeTime, Thickness, DepthPriority));
|
|
|
|
// PrevPoint must be defined to draw junctions
|
|
if( i > 0 )
|
|
{
|
|
Lines.Add(FBatchedLine(PrevPoint, CurrentPoint, DrawColor, LineLifeTime, Thickness, DepthPriority));
|
|
}
|
|
else
|
|
{
|
|
FirstPoint = CurrentPoint;
|
|
}
|
|
|
|
PrevPoint = CurrentPoint;
|
|
}
|
|
// Connect last junction to first
|
|
Lines.Add(FBatchedLine(CurrentPoint, FirstPoint, DrawColor, LineLifeTime, Thickness, DepthPriority));
|
|
|
|
LineBatcher->DrawLines(Lines);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
UE_DRAW_SERVER_DEBUG_ON_EACH_CLIENT(DrawDebugCone, Origin, Direction, Length, AngleWidth, AngleHeight, NumSides, AdjustColorForServer(DrawColor), bPersistentLines, LifeTime, DepthPriority, Thickness);
|
|
}
|
|
}
|
|
|
|
void DrawDebugString(const UWorld* InWorld, FVector const& TextLocation, const FString& Text, class AActor* TestBaseActor, FColor const& TextColor, float Duration, bool bDrawShadow, float FontScale)
|
|
{
|
|
// no debug line drawing on dedicated server
|
|
if (GEngine->GetNetMode(InWorld) != NM_DedicatedServer)
|
|
{
|
|
check((TestBaseActor == nullptr) || (TestBaseActor->GetWorld() == InWorld));
|
|
AActor* BaseAct = (TestBaseActor != nullptr) ? TestBaseActor : InWorld->GetWorldSettings();
|
|
|
|
// iterate through the player controller list
|
|
for( FConstPlayerControllerIterator Iterator = InWorld->GetPlayerControllerIterator(); Iterator; ++Iterator )
|
|
{
|
|
APlayerController* PlayerController = Iterator->Get();
|
|
if (PlayerController && PlayerController->MyHUD && PlayerController->Player)
|
|
{
|
|
PlayerController->MyHUD->AddDebugText(Text, BaseAct, Duration, TextLocation, TextLocation, TextColor, /*bSkipOverwriteCheck=*/ true, /*bAbsoluteLocation=*/ (TestBaseActor==nullptr), /*bKeepAttachedToActor=*/ false, nullptr, FontScale, bDrawShadow);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// We do a bit of converting here if the original call was relative, as there's a check() that the base actor is
|
|
// in the same world as being rendered to (and it might be in a different position on client vs server anyways)
|
|
UE_DRAW_SERVER_DEBUG_ON_EACH_CLIENT(DrawDebugString, (TestBaseActor != nullptr) ? (TextLocation + TestBaseActor->GetActorLocation()) : TextLocation, Text, /*TestBaseActor=*/ nullptr, AdjustColorForServer(TextColor), Duration, bDrawShadow, FontScale);
|
|
}
|
|
}
|
|
|
|
void FlushDebugStrings( const UWorld* InWorld )
|
|
{
|
|
// iterate through the controller list
|
|
for( FConstPlayerControllerIterator Iterator = InWorld->GetPlayerControllerIterator(); Iterator; ++Iterator )
|
|
{
|
|
// if it's a player
|
|
APlayerController* PlayerController = Iterator->Get();
|
|
if (PlayerController && PlayerController->MyHUD)
|
|
{
|
|
PlayerController->MyHUD->RemoveAllDebugStrings();
|
|
}
|
|
}
|
|
}
|
|
|
|
void DrawDebugFrustum(const UWorld* InWorld, const FMatrix& FrustumToWorld, FColor const& Color, bool bPersistentLines, float LifeTime, uint8 DepthPriority, float Thickness)
|
|
{
|
|
// no debug line drawing on dedicated server
|
|
if (GEngine->GetNetMode(InWorld) != NM_DedicatedServer)
|
|
{
|
|
FVector Vertices[2][2][2];
|
|
for(uint32 Z = 0;Z < 2;Z++)
|
|
{
|
|
for(uint32 Y = 0;Y < 2;Y++)
|
|
{
|
|
for(uint32 X = 0;X < 2;X++)
|
|
{
|
|
FVector4 UnprojectedVertex = FrustumToWorld.TransformFVector4(
|
|
FVector4(
|
|
(X ? -1.0f : 1.0f),
|
|
(Y ? -1.0f : 1.0f),
|
|
(Z ? 0.0f : 1.0f),
|
|
1.0f
|
|
)
|
|
);
|
|
Vertices[X][Y][Z] = FVector(UnprojectedVertex) / UnprojectedVertex.W;
|
|
}
|
|
}
|
|
}
|
|
|
|
DrawDebugLine(InWorld, Vertices[0][0][0], Vertices[0][0][1],Color, bPersistentLines, LifeTime, DepthPriority, Thickness);
|
|
DrawDebugLine(InWorld, Vertices[1][0][0], Vertices[1][0][1],Color, bPersistentLines, LifeTime, DepthPriority, Thickness);
|
|
DrawDebugLine(InWorld, Vertices[0][1][0], Vertices[0][1][1],Color, bPersistentLines, LifeTime, DepthPriority, Thickness);
|
|
DrawDebugLine(InWorld, Vertices[1][1][0], Vertices[1][1][1],Color, bPersistentLines, LifeTime, DepthPriority, Thickness);
|
|
|
|
DrawDebugLine(InWorld, Vertices[0][0][0], Vertices[0][1][0],Color, bPersistentLines, LifeTime, DepthPriority, Thickness);
|
|
DrawDebugLine(InWorld, Vertices[1][0][0], Vertices[1][1][0],Color, bPersistentLines, LifeTime, DepthPriority, Thickness);
|
|
DrawDebugLine(InWorld, Vertices[0][0][1], Vertices[0][1][1],Color, bPersistentLines, LifeTime, DepthPriority, Thickness);
|
|
DrawDebugLine(InWorld, Vertices[1][0][1], Vertices[1][1][1],Color, bPersistentLines, LifeTime, DepthPriority, Thickness);
|
|
|
|
DrawDebugLine(InWorld, Vertices[0][0][0], Vertices[1][0][0],Color, bPersistentLines, LifeTime, DepthPriority, Thickness);
|
|
DrawDebugLine(InWorld, Vertices[0][1][0], Vertices[1][1][0],Color, bPersistentLines, LifeTime, DepthPriority, Thickness);
|
|
DrawDebugLine(InWorld, Vertices[0][0][1], Vertices[1][0][1],Color, bPersistentLines, LifeTime, DepthPriority, Thickness);
|
|
DrawDebugLine(InWorld, Vertices[0][1][1], Vertices[1][1][1],Color, bPersistentLines, LifeTime, DepthPriority, Thickness);
|
|
}
|
|
else
|
|
{
|
|
UE_DRAW_SERVER_DEBUG_ON_EACH_CLIENT(DrawDebugFrustum, FrustumToWorld, AdjustColorForServer(Color), bPersistentLines, LifeTime, DepthPriority, Thickness);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static void DrawHalfCircle(const UWorld* InWorld, const FVector& Base, const FVector& X, const FVector& Y, const FColor& Color, float Radius, int32 NumSides, bool bPersistentLines, float LifeTime, uint8 DepthPriority, float Thickness)
|
|
{
|
|
float AngleDelta = 2.0f * (float)UE_PI / ((float)NumSides);
|
|
FVector LastVertex = Base + X * Radius;
|
|
|
|
for(int32 SideIndex = 0; SideIndex < (NumSides/2); SideIndex++)
|
|
{
|
|
FVector Vertex = Base + (X * FMath::Cos(AngleDelta * (SideIndex + 1)) + Y * FMath::Sin(AngleDelta * (SideIndex + 1))) * Radius;
|
|
DrawDebugLine(InWorld, LastVertex, Vertex, Color, bPersistentLines, LifeTime, DepthPriority, Thickness);
|
|
LastVertex = Vertex;
|
|
}
|
|
}
|
|
|
|
void DrawCircle(const UWorld* InWorld, const FVector& Base, const FVector& X, const FVector& Y, const FColor& Color, float Radius, int32 NumSides, bool bPersistentLines, float LifeTime, uint8 DepthPriority, float Thickness)
|
|
{
|
|
const float AngleDelta = 2.0f * UE_PI / NumSides;
|
|
FVector LastVertex = Base + X * Radius;
|
|
|
|
for(int32 SideIndex = 0;SideIndex < NumSides;SideIndex++)
|
|
{
|
|
const FVector Vertex = Base + (X * FMath::Cos(AngleDelta * (SideIndex + 1)) + Y * FMath::Sin(AngleDelta * (SideIndex + 1))) * Radius;
|
|
DrawDebugLine(InWorld, LastVertex, Vertex, Color, bPersistentLines, LifeTime, DepthPriority, Thickness);
|
|
LastVertex = Vertex;
|
|
}
|
|
}
|
|
|
|
void DrawDebugCapsule(const UWorld* InWorld, FVector const& Center, float HalfHeight, float Radius, const FQuat& Rotation, FColor const& Color, bool bPersistentLines, float LifeTime, uint8 DepthPriority, float Thickness)
|
|
{
|
|
// no debug line drawing on dedicated server
|
|
if (GEngine->GetNetMode(InWorld) != NM_DedicatedServer)
|
|
{
|
|
const int32 DrawCollisionSides = 16;
|
|
|
|
FVector Origin = Center;
|
|
FMatrix Axes = FQuatRotationTranslationMatrix(Rotation, FVector::ZeroVector);
|
|
FVector XAxis = Axes.GetScaledAxis( EAxis::X );
|
|
FVector YAxis = Axes.GetScaledAxis( EAxis::Y );
|
|
FVector ZAxis = Axes.GetScaledAxis( EAxis::Z );
|
|
|
|
// Draw top and bottom circles
|
|
float HalfAxis = FMath::Max<float>(HalfHeight - Radius, 1.f);
|
|
FVector TopEnd = Origin + HalfAxis*ZAxis;
|
|
FVector BottomEnd = Origin - HalfAxis*ZAxis;
|
|
|
|
DrawCircle(InWorld, TopEnd, XAxis, YAxis, Color, Radius, DrawCollisionSides, bPersistentLines, LifeTime, DepthPriority, Thickness);
|
|
DrawCircle(InWorld, BottomEnd, XAxis, YAxis, Color, Radius, DrawCollisionSides, bPersistentLines, LifeTime, DepthPriority, Thickness);
|
|
|
|
// Draw domed caps
|
|
DrawHalfCircle(InWorld, TopEnd, YAxis, ZAxis, Color, Radius, DrawCollisionSides, bPersistentLines, LifeTime, DepthPriority, Thickness);
|
|
DrawHalfCircle(InWorld, TopEnd, XAxis, ZAxis, Color, Radius, DrawCollisionSides, bPersistentLines, LifeTime, DepthPriority, Thickness);
|
|
|
|
FVector NegZAxis = -ZAxis;
|
|
|
|
DrawHalfCircle(InWorld, BottomEnd, YAxis, NegZAxis, Color, Radius, DrawCollisionSides, bPersistentLines, LifeTime, DepthPriority, Thickness);
|
|
DrawHalfCircle(InWorld, BottomEnd, XAxis, NegZAxis, Color, Radius, DrawCollisionSides, bPersistentLines, LifeTime, DepthPriority, Thickness);
|
|
|
|
// Draw connected lines
|
|
DrawDebugLine(InWorld, TopEnd + Radius*XAxis, BottomEnd + Radius*XAxis, Color, bPersistentLines, LifeTime, DepthPriority, Thickness);
|
|
DrawDebugLine(InWorld, TopEnd - Radius*XAxis, BottomEnd - Radius*XAxis, Color, bPersistentLines, LifeTime, DepthPriority, Thickness);
|
|
DrawDebugLine(InWorld, TopEnd + Radius*YAxis, BottomEnd + Radius*YAxis, Color, bPersistentLines, LifeTime, DepthPriority, Thickness);
|
|
DrawDebugLine(InWorld, TopEnd - Radius*YAxis, BottomEnd - Radius*YAxis, Color, bPersistentLines, LifeTime, DepthPriority, Thickness);
|
|
}
|
|
else
|
|
{
|
|
UE_DRAW_SERVER_DEBUG_ON_EACH_CLIENT(DrawDebugCapsule, Center, HalfHeight, Radius, Rotation, AdjustColorForServer(Color), bPersistentLines, LifeTime, DepthPriority, Thickness);
|
|
}
|
|
}
|
|
|
|
|
|
void DrawDebugCamera(const UWorld* InWorld, FVector const& Location, FRotator const& Rotation, float FOVDeg, float Scale, FColor const& Color, bool bPersistentLines, float LifeTime, uint8 DepthPriority)
|
|
{
|
|
static float BaseScale = 4.f;
|
|
static FVector BaseProportions(2.f, 1.f, 1.5f);
|
|
|
|
// no debug line drawing on dedicated server
|
|
if (GEngine->GetNetMode(InWorld) != NM_DedicatedServer)
|
|
{
|
|
DrawDebugCoordinateSystem(InWorld, Location, Rotation, BaseScale*Scale, bPersistentLines, LifeTime, DepthPriority);
|
|
FVector Extents = BaseProportions * BaseScale * Scale;
|
|
DrawDebugBox(InWorld, Location, Extents, Rotation.Quaternion(), Color, bPersistentLines, LifeTime, DepthPriority); // lifetime
|
|
|
|
// draw "lens" portion
|
|
FRotationTranslationMatrix Axes(Rotation, Location);
|
|
FVector XAxis = Axes.GetScaledAxis( EAxis::X );
|
|
FVector YAxis = Axes.GetScaledAxis( EAxis::Y );
|
|
FVector ZAxis = Axes.GetScaledAxis( EAxis::Z );
|
|
|
|
FVector LensPoint = Location + XAxis * Extents.X;
|
|
float LensSize = BaseProportions.Z * Scale * BaseScale;
|
|
float HalfLensSize = LensSize * FMath::Tan(FMath::DegreesToRadians(FOVDeg*0.5f));
|
|
FVector Corners[4] =
|
|
{
|
|
LensPoint + XAxis * LensSize + (YAxis * HalfLensSize) + (ZAxis * HalfLensSize),
|
|
LensPoint + XAxis * LensSize + (YAxis * HalfLensSize) - (ZAxis * HalfLensSize),
|
|
LensPoint + XAxis * LensSize - (YAxis * HalfLensSize) - (ZAxis * HalfLensSize),
|
|
LensPoint + XAxis * LensSize - (YAxis * HalfLensSize) + (ZAxis * HalfLensSize),
|
|
};
|
|
|
|
DrawDebugLine(InWorld, LensPoint, Corners[0], Color, bPersistentLines, LifeTime, DepthPriority);
|
|
DrawDebugLine(InWorld, LensPoint, Corners[1], Color, bPersistentLines, LifeTime, DepthPriority);
|
|
DrawDebugLine(InWorld, LensPoint, Corners[2], Color, bPersistentLines, LifeTime, DepthPriority);
|
|
DrawDebugLine(InWorld, LensPoint, Corners[3], Color, bPersistentLines, LifeTime, DepthPriority);
|
|
|
|
DrawDebugLine(InWorld, Corners[0], Corners[1], Color, bPersistentLines, LifeTime, DepthPriority);
|
|
DrawDebugLine(InWorld, Corners[1], Corners[2], Color, bPersistentLines, LifeTime, DepthPriority);
|
|
DrawDebugLine(InWorld, Corners[2], Corners[3], Color, bPersistentLines, LifeTime, DepthPriority);
|
|
DrawDebugLine(InWorld, Corners[3], Corners[0], Color, bPersistentLines, LifeTime, DepthPriority);
|
|
}
|
|
else
|
|
{
|
|
UE_DRAW_SERVER_DEBUG_ON_EACH_CLIENT(DrawDebugCamera, Location, Rotation, FOVDeg, Scale, AdjustColorForServer(Color), bPersistentLines, LifeTime, DepthPriority);
|
|
}
|
|
}
|
|
|
|
|
|
void DrawDebugFloatHistory(UWorld const & WorldRef, FDebugFloatHistory const & FloatHistory, FTransform const & DrawTransform, FVector2D const & DrawSize, FColor const & DrawColor, bool const & bPersistent, float const & LifeTime, uint8 const & DepthPriority)
|
|
{
|
|
int const NumSamples = FloatHistory.GetNumSamples();
|
|
if (NumSamples >= 2)
|
|
{
|
|
FVector DrawLocation = DrawTransform.GetLocation();
|
|
FVector const AxisX = DrawTransform.GetUnitAxis(EAxis::Y);
|
|
FVector const AxisY = DrawTransform.GetUnitAxis(EAxis::Z);
|
|
FVector const AxisXStep = AxisX * DrawSize.X / float(NumSamples);
|
|
FVector const AxisYStep = AxisY * DrawSize.Y / FMath::Max(FloatHistory.GetMinMaxRange(), UE_KINDA_SMALL_NUMBER);
|
|
|
|
// Frame
|
|
DrawDebugLine(&WorldRef, DrawLocation, DrawLocation + AxisX * DrawSize.X, DrawColor, bPersistent, LifeTime, DepthPriority);
|
|
DrawDebugLine(&WorldRef, DrawLocation, DrawLocation + AxisY * DrawSize.Y, DrawColor, bPersistent, LifeTime, DepthPriority);
|
|
DrawDebugLine(&WorldRef, DrawLocation + AxisY * DrawSize.Y, DrawLocation + AxisX * DrawSize.X + AxisY * DrawSize.Y, DrawColor, bPersistent, LifeTime, DepthPriority);
|
|
DrawDebugLine(&WorldRef, DrawLocation + AxisX * DrawSize.X, DrawLocation + AxisX * DrawSize.X + AxisY * DrawSize.Y, DrawColor, bPersistent, LifeTime, DepthPriority);
|
|
|
|
TArray<float> const & Samples = FloatHistory.GetSamples();
|
|
|
|
TArray<FVector> Verts;
|
|
Verts.AddUninitialized(NumSamples * 2);
|
|
|
|
TArray<int32> Indices;
|
|
Indices.AddUninitialized((NumSamples - 1) * 6);
|
|
|
|
Verts[0] = DrawLocation;
|
|
Verts[1] = DrawLocation + AxisYStep * Samples[0];
|
|
|
|
for (int HistoryIndex = 1; HistoryIndex < NumSamples; HistoryIndex++)
|
|
{
|
|
DrawLocation += AxisXStep;
|
|
|
|
int const VertIndex = (HistoryIndex - 1) * 2;
|
|
Verts[VertIndex + 2] = DrawLocation;
|
|
Verts[VertIndex + 3] = DrawLocation + AxisYStep * FMath::Clamp(Samples[HistoryIndex], FloatHistory.GetMinValue(), FloatHistory.GetMaxValue());
|
|
|
|
int const StartIndex = (HistoryIndex - 1) * 6;
|
|
Indices[StartIndex + 0] = VertIndex + 0; Indices[StartIndex + 1] = VertIndex + 1; Indices[StartIndex + 2] = VertIndex + 3;
|
|
Indices[StartIndex + 3] = VertIndex + 0; Indices[StartIndex + 4] = VertIndex + 3; Indices[StartIndex + 5] = VertIndex + 2;
|
|
}
|
|
|
|
DrawDebugMesh(&WorldRef, Verts, Indices, DrawColor, bPersistent, LifeTime, DepthPriority);
|
|
}
|
|
}
|
|
|
|
void DrawDebugFloatHistory(UWorld const & WorldRef, FDebugFloatHistory const & FloatHistory, FVector const & DrawLocation, FVector2D const & DrawSize, FColor const & DrawColor, bool const & bPersistent, float const & LifeTime, uint8 const & DepthPriority)
|
|
{
|
|
APlayerController * PlayerController = WorldRef.GetGameInstance() != nullptr ? WorldRef.GetGameInstance()->GetFirstLocalPlayerController() : nullptr;
|
|
FRotator const DrawRotation = (PlayerController && PlayerController->PlayerCameraManager) ? PlayerController->PlayerCameraManager->GetCameraRotation() : FRotator(0, 0, 0);
|
|
|
|
FTransform const DrawTransform(DrawRotation, DrawLocation);
|
|
DrawDebugFloatHistory(WorldRef, FloatHistory, DrawTransform, DrawSize, DrawColor, bPersistent, LifeTime, DepthPriority);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
// Debug draw canvas operations
|
|
|
|
void DrawDebugCanvas2DLine(UCanvas* Canvas, const FVector& Start, const FVector& End, const FLinearColor& LineColor)
|
|
{
|
|
FCanvasLineItem LineItem;
|
|
LineItem.Origin = Start;
|
|
LineItem.EndPos = End;
|
|
LineItem.SetColor(LineColor);
|
|
|
|
LineItem.Draw(Canvas->Canvas);
|
|
}
|
|
|
|
void DrawDebugCanvasLine(UCanvas* Canvas, const FVector& Start, const FVector& End, const FLinearColor& LineColor)
|
|
{
|
|
DrawDebugCanvas2DLine(Canvas, Canvas->Project(Start), Canvas->Project(End), LineColor);
|
|
}
|
|
|
|
void DrawDebugCanvasCircle(UCanvas* Canvas, const FVector& Base, const FVector& X, const FVector& Y, FColor Color, float Radius, int32 NumSides)
|
|
{
|
|
const float AngleDelta = 2.0f * UE_PI / NumSides;
|
|
FVector LastVertex = Base + X * Radius;
|
|
|
|
for(int32 SideIndex = 0;SideIndex < NumSides;SideIndex++)
|
|
{
|
|
const FVector Vertex = Base + (X * FMath::Cos(AngleDelta * (SideIndex + 1)) + Y * FMath::Sin(AngleDelta * (SideIndex + 1))) * Radius;
|
|
DrawDebugCanvasLine(Canvas, LastVertex, Vertex, Color);
|
|
LastVertex = Vertex;
|
|
}
|
|
}
|
|
|
|
void DrawDebugCanvasWireSphere(UCanvas* Canvas, const FVector& Base, FColor Color, float Radius, int32 NumSides)
|
|
{
|
|
DrawDebugCanvasCircle(Canvas, Base, FVector(1,0,0), FVector(0,1,0), Color, Radius, NumSides);
|
|
DrawDebugCanvasCircle(Canvas, Base, FVector(1,0,0), FVector(0,0,1), Color, Radius, NumSides);
|
|
DrawDebugCanvasCircle(Canvas, Base, FVector(0,1,0), FVector(0,0,1), Color, Radius, NumSides);
|
|
}
|
|
|
|
void DrawDebugCanvasWireCone(UCanvas* Canvas, const FTransform& Transform, float ConeRadius, float ConeAngle, int32 ConeSides, FColor Color)
|
|
{
|
|
static const float TwoPI = 2.0f * UE_PI;
|
|
static const float ToRads = UE_PI / 180.0f;
|
|
static const float MaxAngle = 89.0f * ToRads + 0.001f;
|
|
const float ClampedConeAngle = FMath::Clamp(ConeAngle * ToRads, 0.001f, MaxAngle);
|
|
const float SinClampedConeAngle = FMath::Sin( ClampedConeAngle );
|
|
const float CosClampedConeAngle = FMath::Cos( ClampedConeAngle );
|
|
const FVector ConeDirection(1,0,0);
|
|
const FVector ConeUpVector(0,1,0);
|
|
const FVector ConeLeftVector(0,0,1);
|
|
|
|
TArray<FVector> Verts;
|
|
Verts.AddUninitialized( ConeSides );
|
|
|
|
for ( int32 i = 0 ; i < Verts.Num() ; ++i )
|
|
{
|
|
const float Theta = static_cast<float>( (TwoPI * i) / Verts.Num() );
|
|
Verts[i] = (ConeDirection * (ConeRadius * CosClampedConeAngle)) +
|
|
((SinClampedConeAngle * ConeRadius * FMath::Cos( Theta )) * ConeUpVector) +
|
|
((SinClampedConeAngle * ConeRadius * FMath::Sin( Theta )) * ConeLeftVector);
|
|
}
|
|
|
|
// Transform to world space.
|
|
for ( int32 i = 0 ; i < Verts.Num() ; ++i )
|
|
{
|
|
Verts[i] = Transform.TransformPosition( Verts[i] );
|
|
}
|
|
|
|
// Draw spokes.
|
|
for ( int32 i = 0 ; i < Verts.Num(); ++i )
|
|
{
|
|
DrawDebugCanvasLine( Canvas, Transform.GetLocation(), Verts[i], Color );
|
|
}
|
|
|
|
// Draw rim.
|
|
for ( int32 i = 0 ; i < Verts.Num()-1 ; ++i )
|
|
{
|
|
DrawDebugCanvasLine( Canvas, Verts[i], Verts[i+1], Color );
|
|
}
|
|
DrawDebugCanvasLine( Canvas, Verts[Verts.Num()-1], Verts[0], Color );
|
|
}
|
|
|
|
//
|
|
// Canvas 2D
|
|
//
|
|
|
|
void DrawDebugCanvas2DLine(UCanvas* Canvas, const FVector2D& StartPosition, const FVector2D& EndPosition, const FLinearColor& LineColor, const float& LineThickness)
|
|
{
|
|
if (Canvas)
|
|
{
|
|
FCanvasLineItem LineItem(StartPosition, EndPosition);
|
|
LineItem.LineThickness = LineThickness;
|
|
LineItem.SetColor(LineColor);
|
|
Canvas->DrawItem(LineItem);
|
|
}
|
|
}
|
|
|
|
void DrawDebugCanvas2DCircle(UCanvas* Canvas, const FVector2D& Center, float Radius, int32 NumSides, const FLinearColor& LineColor, const float& LineThickness)
|
|
{
|
|
const float AngleDelta = 2.0f * UE_PI / NumSides;
|
|
FVector2D AxisX(1.f, 0.f);
|
|
FVector2D AxisY(0.f, -1.f);
|
|
FVector2D LastVertex = Center + AxisX * Radius;
|
|
|
|
for (int32 SideIndex = 0; SideIndex < NumSides; SideIndex++)
|
|
{
|
|
const FVector2D Vertex = Center + (AxisX * FMath::Cos(AngleDelta * (SideIndex + 1)) + AxisY * FMath::Sin(AngleDelta * (SideIndex + 1))) * Radius;
|
|
DrawDebugCanvas2DLine(Canvas, LastVertex, Vertex, LineColor, LineThickness);
|
|
LastVertex = Vertex;
|
|
}
|
|
}
|
|
|
|
void DrawDebugCanvas2DBox(UCanvas* Canvas, const FBox2D& Box, const FLinearColor& LineColor, const float& LineThickness)
|
|
{
|
|
if (Canvas)
|
|
{
|
|
FCanvasBoxItem BoxItem(Box.Min, Box.GetSize());
|
|
BoxItem.LineThickness = LineThickness;
|
|
BoxItem.SetColor(LineColor);
|
|
|
|
Canvas->DrawItem(BoxItem);
|
|
}
|
|
}
|
|
|
|
#endif // ENABLE_DRAW_DEBUG
|