UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
DebugDrawQueue.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2#pragma once
3
5#include "Chaos/AABB.h"
7#include "Containers/List.h"
8#include "Math/Vector.h"
9#include "Math/Color.h"
10#include "Math/Quat.h"
11#include "Misc/ScopeLock.h"
12#include "HAL/ThreadSafeBool.h"
13#include "HAL/IConsoleManager.h"
14
17
18class AActor;
19
20
21#if CHAOS_DEBUG_DRAW
22namespace Chaos
23{
26
28template<typename ElementType>
30{
31public:
32
35 FirstElement(nullptr)
36 {}
37
42 void AddElement(TList<ElementType>* Element)
43 {
44 // Link the element at the beginning of the list.
46 do
47 {
50 } while (FPlatformAtomics::InterlockedCompareExchangePointer((void**)&FirstElement, Element, LocalFirstElement) != LocalFirstElement);
51 }
52
58 {
59 // Atomically read the complete list and clear the shared head pointer.
61 do
62 {
64 } while (FPlatformAtomics::InterlockedCompareExchangePointer((void**)&FirstElement, NULL, LocalFirstElement) != LocalFirstElement);
65 return LocalFirstElement;
66 }
67
71 void Clear()
72 {
73 while (FirstElement)
74 {
75 // Atomically read the complete list and clear the shared head pointer.
77
78 // Delete all elements in the local list.
79 while (Element)
80 {
81 TList<ElementType>* NextElement = Element->Next;
82 delete Element;
83 Element = NextElement;
84 };
85 };
86 }
87
88private:
89
91};
92
95{
96public:
97 enum EBuffer
98 {
99 Internal = 0,
100 External = 1
101 };
102
104 {
106
107 // Move the buffer into the output, and reserve space in the new buffer to prevent excess allocations and copies
108 int Capacity = CommandQueue.Max();
109 OutDrawCommands = MoveTemp(CommandQueue);
110 CommandQueue.Reserve(Capacity);
112 }
113
114 void DrawDebugPoint(const FVector& Position, const FColor& Color, bool bPersistentLines, float LifeTime, uint8 DepthPriority, float Thickness)
115 {
116 if (IsDebugDrawingEnabled())
117 {
119 if (AcceptCommand(1, Position))
120 {
121 AddCommand(FLatentDrawCommand::DrawPoint(Position, Color, bPersistentLines, LifeTime, DepthPriority, Thickness));
122 }
123 }
124 }
125
126 void DrawDebugLine(const FVector& LineStart, const FVector& LineEnd, const FColor& Color, bool bPersistentLines = false, float LifeTime = -1.f, uint8 DepthPriority = 0, float Thickness = 0.f)
127 {
128 if (IsDebugDrawingEnabled())
129 {
131 if (AcceptCommand(1, LineStart))
132 {
133 AddCommand(FLatentDrawCommand::DrawLine(LineStart, LineEnd, Color, bPersistentLines, LifeTime, DepthPriority, Thickness));
134 }
135 }
136 }
137
138 void DrawDebugDirectionalArrow(const FVector& LineStart, const FVector& LineEnd, float ArrowSize, const FColor& Color, bool bPersistentLines = false, float LifeTime = -1.f, uint8 DepthPriority = 0, float Thickness = 0.f)
139 {
140 if (IsDebugDrawingEnabled())
141 {
143 if (AcceptCommand(3, LineStart))
144 {
145 AddCommand(FLatentDrawCommand::DrawDirectionalArrow(LineStart, LineEnd, ArrowSize, Color, bPersistentLines, LifeTime, DepthPriority, Thickness));
146 }
147 }
148 }
149
150 void DrawDebugCoordinateSystem(const FVector& Position, const FRotator& AxisRot, FReal Scale, bool bPersistentLines = false, float LifeTime = -1.f, uint8 DepthPriority = 0, float Thickness = 0.f)
151 {
152 if (IsDebugDrawingEnabled())
153 {
155
156 FRotationMatrix R(AxisRot);
157 FVector const X = R.GetScaledAxis(EAxis::X);
158 FVector const Y = R.GetScaledAxis(EAxis::Y);
159 FVector const Z = R.GetScaledAxis(EAxis::Z);
160
161 if (AcceptCommand(3, Position))
162 {
163 AddCommand(FLatentDrawCommand::DrawLine(Position, Position + X * Scale, FColor::Red, bPersistentLines, LifeTime, DepthPriority, Thickness));
164 AddCommand(FLatentDrawCommand::DrawLine(Position, Position + Y * Scale, FColor::Green, bPersistentLines, LifeTime, DepthPriority, Thickness));
165 AddCommand(FLatentDrawCommand::DrawLine(Position, Position + Z * Scale, FColor::Blue, bPersistentLines, LifeTime, DepthPriority, Thickness));
166 }
167 }
168 }
169
170
171 void DrawDebugSphere(FVector const& Center, FReal Radius, int32 Segments, const FColor& Color, bool bPersistentLines = false, float LifeTime = -1.f, uint8 DepthPriority = 0, float Thickness = 0.f)
172 {
173 if (IsDebugDrawingEnabled())
174 {
176 const int Cost = Segments * Segments;
177 if (AcceptCommand(Cost, Center))
178 {
179 AddCommand(FLatentDrawCommand::DrawDebugSphere(Center, Radius, Segments, Color, bPersistentLines, LifeTime, DepthPriority, Thickness));
180 }
181 }
182 }
183
184 void DrawDebugBox(FVector const& Center, FVector const& Extent, const FQuat& Rotation, FColor const& Color, bool bPersistentLines, float LifeTime, uint8 DepthPriority, float Thickness)
185 {
186 if (IsDebugDrawingEnabled())
187 {
189 if (AcceptCommand(12, Center))
190 {
191 AddCommand(FLatentDrawCommand::DrawDebugBox(Center, Extent, Rotation, Color, bPersistentLines, LifeTime, DepthPriority, Thickness));
192 }
193 }
194 }
195
196 void DrawDebugString(FVector const& TextLocation, const FString& Text, class AActor* TestBaseActor, FColor const& Color, float Duration, bool bDrawShadow, float FontScale)
197 {
198 if (IsDebugDrawingEnabled())
199 {
201 int Cost = Text.Len();
202 if (AcceptCommand(Cost, TextLocation))
203 {
204 AddCommand(FLatentDrawCommand::DrawDebugString(TextLocation, Text, TestBaseActor, Color, Duration, bDrawShadow, FontScale));
205 }
206 }
207 }
208
209 void DrawDebugCircle(const FVector& Center, FReal Radius, int32 Segments, const FColor& Color, bool bPersistentLines, float LifeTime, uint8 DepthPriority, float Thickness, const FVector& YAxis, const FVector& ZAxis, bool bDrawAxis)
210 {
211 if (IsDebugDrawingEnabled())
212 {
215 {
216 AddCommand(FLatentDrawCommand::DrawDebugCircle(Center, Radius, Segments, Color, bPersistentLines, LifeTime, DepthPriority, Thickness, YAxis, ZAxis, bDrawAxis));
217 }
218 }
219 }
220
221 void DrawDebugCapsule(const FVector& Center, FReal HalfHeight, FReal Radius, const FQuat& Rotation, const FColor& Color, bool bPersistentLines, float LifeTime, uint8 DepthPriority, float Thickness)
222 {
223 if (IsDebugDrawingEnabled())
224 {
226 if (AcceptCommand(16, Center))
227 {
228 AddCommand(FLatentDrawCommand::DrawDebugCapsule(Center, HalfHeight, Radius, Rotation, Color, bPersistentLines, LifeTime, DepthPriority, Thickness));
229 }
230 }
231 }
232
233 void SetEnabled(bool bInEnabled)
234 {
237 }
238
240 {
243 }
244
245 void SetRegionOfInterest(const FVector& Pos, float InRadius)
246 {
248 CenterOfInterest = Pos;
250 }
251
253 {
255 }
256
258 {
260 }
261
262 bool IsInRegionOfInterest(FVector Pos) const
263 {
264 return IsInRegionOfInterestImpl(Pos);
265 }
266
267 bool IsInRegionOfInterest(FVector Pos, FReal Radius) const
268 {
269 return IsInRegionOfInterestImpl(Pos, Radius);
270 }
271
272 bool IsInRegionOfInterest(FAABB3 Bounds) const
273 {
274 return IsInRegionOfInterestImpl(Bounds);
275 }
276
277 CHAOS_API void SetConsumerActive(void* Consumer, bool bConsumerActive);
278
279 static CHAOS_API FDebugDrawQueue& GetInstance();
280
281 static bool IsDebugDrawingEnabled()
282 {
283 // Don't queue up debug draws unless something is consuming the queue, otherwise it can build up forever
284 return GetInstance().bEnableDebugDrawing && (GetInstance().NumConsumers > 0);
285 }
286
287private:
290 , MaxCommandCost(10000)
291 , CenterOfInterest(FVector::ZeroVector)
294 {}
296
298 {
300 {
301 ChaosDD::Private::FChaosDDFrameWriter DDWriter = ChaosDD::Private::FChaosDDContext::Get().GetWriter();
302 return DDWriter.GetDrawRegion().Center;
303 }
304
305 return CenterOfInterest;
306 }
307
309 {
311 {
312 ChaosDD::Private::FChaosDDFrameWriter DDWriter = ChaosDD::Private::FChaosDDContext::Get().GetWriter();
313 return DDWriter.GetDrawRegion().W;
314 }
315
316 return RadiusOfInterest;
317 }
318
319 bool IsInRegionOfInterestImpl(FVector Pos) const
320 {
322 {
323 ChaosDD::Private::FChaosDDFrameWriter DDWriter = ChaosDD::Private::FChaosDDContext::Get().GetWriter();
324 return DDWriter.IsInDrawRegion(Pos);
325 }
326
328 }
329
330 bool IsInRegionOfInterestImpl(FVector Pos, FReal Radius) const
331 {
333 {
334 ChaosDD::Private::FChaosDDFrameWriter DDWriter = ChaosDD::Private::FChaosDDContext::Get().GetWriter();
335 return DDWriter.IsInDrawRegion(FSphere3d(Pos, Radius));
336 }
337
338 return (RadiusOfInterest <= 0.0f) || ((Pos - CenterOfInterest).SizeSquared() < (RadiusOfInterest + Radius) * (RadiusOfInterest + Radius));
339 }
340
341 bool IsInRegionOfInterestImpl(FAABB3 Bounds) const
342 {
344 {
345 ChaosDD::Private::FChaosDDFrameWriter DDWriter = ChaosDD::Private::FChaosDDContext::Get().GetWriter();
346 return DDWriter.IsInDrawRegion(FBox3d(Bounds.Min(), Bounds.Max()));
347 }
348 return Bounds.ThickenSymmetrically(FVec3(RadiusOfInterest)).Contains(CenterOfInterest);
349 }
350
351 bool AcceptCommand(int Cost, const FVec3& Position)
352 {
354 {
355 ChaosDD::Private::FChaosDDFrameWriter DDWriter = ChaosDD::Private::FChaosDDContext::Get().GetWriter();
356 if (DDWriter.IsInDrawRegion(Position))
357 {
358 return DDWriter.AddToCost(Cost);
359 }
360 return false;
361 }
362
363 // If we get here...
364 // This thread has not been set up for the new debug draw system so default back to the old
365 // way that has issues with timing in async mode.
367 {
369 {
370 RequestedCommandCost += Cost;
371 return IsInBudget();
372 }
373 }
374
375 return false;
376 }
377
378 void AddCommand(const FLatentDrawCommand& Command)
379 {
380 // Try to add to the new debug draw system which queues commands per World and ticking thread
382 {
383 ChaosDD::Private::FChaosDDContext::GetWriter().EnqueueLatentCommand(Command);
384 return;
385 }
386
387 // If we get here...
388 // This thread has not been set up for the new debug draw system so default back to the old
389 // way that has issues with timing in async mode.
391 {
392 CommandQueue.Add(Command);
393 }
394 }
395
396 bool IsInBudget() const
397 {
399 }
400
405
407 int32 NumConsumers;
409
413};
414}
415#endif
#define NULL
Definition oodle2base.h:134
FPlatformTypes::int32 int32
A 32-bit signed integer.
Definition Platform.h:1125
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
UE::FPlatformRecursiveMutex FCriticalSection
Definition CriticalSection.h:53
ENGINE_API void DrawDebugCoordinateSystem(const UWorld *InWorld, FVector const &AxisLoc, FRotator const &AxisRot, float Scale, bool bPersistentLines=false, float LifeTime=-1.f, uint8 DepthPriority=0, float Thickness=0.f)
ENGINE_API void DrawDebugBox(const UWorld *InWorld, FVector const &Center, FVector const &Extent, FColor const &Color, bool bPersistentLines=false, float LifeTime=-1.f, uint8 DepthPriority=0, float Thickness=0.f)
ENGINE_API void DrawDebugCapsule(const UWorld *InWorld, FVector const &Center, float HalfHeight, float Radius, const FQuat &Rotation, FColor const &Color, bool bPersistentLines=false, float LifeTime=-1.f, uint8 DepthPriority=0, float Thickness=0)
ENGINE_API void DrawDebugCircle(const UWorld *InWorld, const FMatrix &TransformMatrix, double Radius, int32 Segments, const FColor &Color, bool bPersistentLines=false, float LifeTime=-1.f, uint8 DepthPriority=0, float Thickness=0.f, bool bDrawAxis=true)
ENGINE_API void DrawDebugString(const UWorld *InWorld, FVector const &TextLocation, const FString &Text, class AActor *TestBaseActor=NULL, FColor const &TextColor=FColor::White, float Duration=-1.000000, bool bDrawShadow=false, float FontScale=1.f)
ENGINE_API void DrawDebugLine(const UWorld *InWorld, FVector const &LineStart, FVector const &LineEnd, FColor const &Color, bool bPersistentLines=false, float LifeTime=-1.f, uint8 DepthPriority=0, float Thickness=0.f)
ENGINE_API void DrawDebugPoint(const UWorld *InWorld, FVector const &Position, float Size, FColor const &PointColor, bool bPersistentLines=false, float LifeTime=-1.f, uint8 DepthPriority=0)
ENGINE_API void DrawDebugDirectionalArrow(const UWorld *InWorld, FVector const &LineStart, FVector const &LineEnd, float ArrowSize, FColor const &Color, bool bPersistentLines=false, float LifeTime=-1.f, uint8 DepthPriority=0, float Thickness=0.f)
ENGINE_API void DrawDebugSphere(const UWorld *InWorld, FVector const &Center, float Radius, int32 Segments, FColor const &Color, bool bPersistentLines=false, float LifeTime=-1.f, uint8 DepthPriority=0, float Thickness=0.f)
#define X(Name, Desc)
Definition FormatStringSan.h:47
UE::Math::TSphere< double > FSphere3d
Definition MathFwd.h:67
UE::Math::TBox< double > FBox3d
Definition MathFwd.h:68
UE_INTRINSIC_CAST UE_REWRITE constexpr std::remove_reference_t< T > && MoveTemp(T &&Obj) noexcept
Definition UnrealTemplate.h:520
FRWLock Lock
Definition UnversionedPropertySerialization.cpp:921
uint8_t uint8
Definition binka_ue_file_header.h:8
Definition Actor.h:257
Definition ScopeLock.h:141
Definition Array.h:670
Definition List.h:824
FGameThreadAudioCommandQueue CommandQueue
Definition AudioThread.cpp:222
Definition SkeletalMeshComponent.h:307
TVector< FReal, 3 > FVec3
Definition Core.h:17
@ Z
Definition Axis.h:15
@ Y
Definition Axis.h:14
@ X
Definition Axis.h:13
Chaos::FReal FReal
Definition ImmediatePhysicsCore_Chaos.h:33
Definition ByteSwap.h:14
void SetEnabled(bool bInEnabled)
Definition ShaderPrint.cpp:317
@ Element
Definition Visu.h:18
double SizeSquared(const T &Value)
Definition SplineMath.h:172
@ false
Definition radaudio_common.h:23
Definition Color.h:486
static CORE_API const FColor Blue
Definition Color.h:754
static CORE_API const FColor Red
Definition Color.h:752
static CORE_API const FColor Green
Definition Color.h:753