UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
ClassTree.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3/*=============================================================================
4 ClassTree.h: Class hierarchy management classes.
5=============================================================================*/
6
7#pragma once
8
9#include "CoreMinimal.h"
10#include "UObject/Object.h"
11#include "UObject/Class.h"
12#include "Containers/List.h"
13#include "UObject/UObjectHash.h"
15
24
31{
32 UClass* Class;
33 FClassTree* Parent;
34 TArray<FClassTree*> Children;
36
37 //@name Utility functions used for internal management of class tree
39
48 bool AddChildClass( UClass* ChildClass )
49 {
51
52 // if the new class is already in the tree, don't add it again
53 if ( ChildClass == Class )
54 return true;
55
56 // if the new class isn't a child of the current node, check to see if we need to insert
57 // the new class into the tree at this node's location (i.e. the new class is actually the parent
58 // of the current node's class)
59 if ( !ChildClass->IsChildOf(Class) )
60 {
61 if ( Parent )
62 {
63 if ( ChildClass != Parent->GetClass() && // if our parent node's class is not the same as the new class
64 Class->IsChildOf(ChildClass) ) // and the new class is a parent class of this node's class
65 {
66 // make the new class our parent node
67 Parent->ReplaceChild(ChildClass,this);
68 return true;
69 }
70 }
71
72 return false;
73 }
74
75 // the new class belongs on this branch - find out if it belongs in any of our child nodes
76 for ( int32 ChildIndex = 0; ChildIndex < Children.Num(); ChildIndex++ )
77 {
78 if ( Children[ChildIndex]->AddChildClass(ChildClass) )
79 return 1;
80 }
81
82 // none of our child nodes accepted the new class - so it'll be a child of this node
84 AddChildNode(NewChild);
85 return 1;
86 }
87
97 int32 AddChildNode( FClassTree* NewChild )
98 {
100
101 NewChild->Parent = this;
102 int32 i = Children.Find(NewChild);
103 if ( i == INDEX_NONE )
104 {
105 for ( i = 0; i < Children.Num(); i++ )
106 {
107 FClassTree* Child = Children[i];
108
109 // insert this class sorted alphabetically
110 if ( FCString::Stricmp(*Child->GetClass()->GetName(), *NewChild->GetClass()->GetName()) >= 0 )
111 {
112 break;
113 }
114 }
115
116 Children.InsertUninitialized(i);
117 Children[i] = NewChild;
118 }
119
120 return i;
121 }
122
132 void ReplaceChild( UClass* NewChild, FClassTree* CurrentChild )
133 {
135
136 // find the index of the old child
137 int32 OldIndex = Children.Find(CurrentChild);
138
139 // remove it from our list of children
140 Children.RemoveAt(OldIndex);
141
142 // then check to see if any existing children really belong under this new child
143 for ( int32 ChildIndex = Children.Num() - 1; ChildIndex >= 0; ChildIndex-- )
144 {
145 FClassTree* ChildNode = Children[ChildIndex];
147 if ( ChildClass->IsChildOf(NewChild) )
148 {
149 // remove this class from our list of Children
150 Children.RemoveAt(ChildIndex);
151
152 // and insert it under the new child
153 NewChildNode->AddChildNode(ChildNode);
154 }
155 }
156
157 // add a child node for the new class
158 int32 NewIndex = AddChildNode(NewChildNode);
159
160 // add the old node to the new node as a child
161 Children[NewIndex]->AddChildNode(CurrentChild);
162 }
163
164
173 FClassTree* GetNode( UClass* SearchClass, bool bBruteForce )
174 {
175 FClassTree* Result(NULL);
176
177 if ( SearchClass == Class )
178 Result = this;
179
180 else if ( bBruteForce || SearchClass->IsChildOf(Class) )
181 {
182 for ( int32 i = 0; i < Children.Num(); i++ )
183 {
184 Result = Children[i]->GetNode(SearchClass,bBruteForce);
185 if ( Result != NULL )
186 break;
187 }
188 }
189
190 return Result;
191 }
192
201 int32 FindChildIndex( UClass* SearchClass ) const
202 {
203 for ( int32 i = 0; i < Children.Num(); i++ )
204 {
205 if ( Children[i]->GetClass() == SearchClass )
206 return i;
207 }
208
209 return INDEX_NONE;
210 }
211
213
214public:
215
220 {
221 FClassTree* RootNode = GetRootNode();
222 for ( TObjectIterator<UClass> It; It; ++It )
223 {
224 RootNode->AddClass(*It);
225 }
226 }
227
242 {
243 // in order to ensure that all classes are placed into the correct locations in the tree,
244 // only the root node can accept new classes
246 for ( ReceivingNode = this; ReceivingNode->Parent != NULL; ReceivingNode = ReceivingNode->Parent );
247
248 return ReceivingNode->AddChildClass(ChildClass);
249 }
250
257 {
258 return Class;
259 }
260
261private:
262 struct FScopedRecurseDepthCounter
263 {
264 int32* Counter;
265 FScopedRecurseDepthCounter(int32* InCounter)
266 : Counter(InCounter)
267 {
268 (*Counter)++;
269 }
270 ~FScopedRecurseDepthCounter()
271 {
272 (*Counter)--;
273 }
274 };
275public:
276
283 void GetChildClasses( TArray<FClassTree*>& ChildClasses, bool bRecurse=false )
284 {
285 static int32 RecurseDepth = 0;
286 if (RecurseDepth == 0)
287 {
288 ChildClasses.Empty();
289 }
290 for ( int32 i = 0; i < Children.Num(); i++ )
291 {
292 ChildClasses.Add( Children[i] );
293 }
294
295 if ( bRecurse )
296 {
297 FScopedRecurseDepthCounter Counter(&RecurseDepth);
298 for ( int32 i = 0; i < Children.Num(); i++ )
299 {
300 Children[i]->GetChildClasses(ChildClasses, bRecurse);
301 }
302 }
303 }
304
311 void GetChildClasses( TArray<const FClassTree*>& ChildClasses, bool bRecurse=false ) const
312 {
313 static int32 RecurseDepth = 0;
314 if (RecurseDepth == 0)
315 {
316 ChildClasses.Empty();
317 }
318 for ( int32 i = 0; i < Children.Num(); i++ )
319 {
320 ChildClasses.Add( Children[i] );
321 }
322
323 if ( bRecurse )
324 {
325 FScopedRecurseDepthCounter Counter(&RecurseDepth);
326 for ( int32 i = 0; i < Children.Num(); i++ )
327 {
328 Children[i]->GetChildClasses(ChildClasses, bRecurse);
329 }
330 }
331 }
332
341 template< class Comparator >
342 void GetChildClasses( TArray<UClass*>& ChildClasses, const Comparator& Mask, bool bRecurse=false ) const
343 {
344 for ( int32 i = 0; i < Children.Num(); i++ )
345 {
346 FClassTree* ChildNode = Children[i];
347 if ( Mask(ChildNode->GetClass()) )
348 {
349 ChildClasses.Add( ChildNode->GetClass() );
350 }
351
352 if ( bRecurse )
353 {
354 ChildNode->GetChildClasses(ChildClasses, Mask, bRecurse);
355 }
356 }
357 }
358
372 template< class Comparator >
374 {
376 if ( Mask.IsValidClass(this) )
377 {
378 ResultTree = new FClassTree(Class);
379 for ( int32 ChildIndex = 0; ChildIndex < Children.Num(); ChildIndex++ )
380 {
381 FClassTree* ChildNode = Children[ChildIndex]->GenerateMaskedClassTree(Mask);
382 if ( ChildNode != NULL )
383 {
384 ChildNode->Parent = ResultTree;
385 ResultTree->Children.Add(ChildNode);
386 }
387 }
388 }
389
390 return ResultTree;
391 }
392
397 {
398 FClassTree* RootNode;
399 for ( RootNode = this; RootNode->Parent != NULL; RootNode = RootNode->Parent );
400 return RootNode;
401 }
402
406 const FClassTree* GetRootNode() const
407 {
408 const FClassTree* RootNode;
409 for ( RootNode = this; RootNode->Parent != NULL; RootNode = RootNode->Parent );
410 return RootNode;
411 }
412
421 {
422 return GetNode(SearchClass,false);
423 }
424
433 {
434 if ( SearchClass == Class )
435 return this;
436
437 if (!SearchClass->IsChildOf(Class))
438 return NULL;
439
440 for (auto Child : Children)
441 {
442 if (auto Result = Child->FindNode(SearchClass))
443 return Result;
444 }
445
446 return NULL;
447 }
448
458 {
459 // in order to ensure that all classes are placed into the correct locations in the tree,
460 // only the root node can accept new classes
461 if ( Parent != NULL )
462 {
464 for ( ReceivingNode = this; ReceivingNode->Parent != NULL; ReceivingNode = ReceivingNode->Parent );
465
467 }
468
470
472
473 // find the node associated with SearchClass's new SuperClass
475 if (!NewParentNode)
476 {
477 // if that class hasn't been added yet, add it now.
479 return false;
480
481 NewParentNode = GetNode(NewParentClass);
482 }
484
485 // find the node for the class that changed SuperClass
486 if (FClassTree* ClassNode = GetNode(SearchClass,true))
487 {
488 // if the node has an existing parent, remove it from the parent's Children array
489 if (ClassNode->Parent)
490 {
491 ClassNode->Parent->Children.RemoveSingle(ClassNode);
492 }
493
494 // move the node to the new SuperClass
495 return NewParentNode->AddChildNode(ClassNode) != INDEX_NONE;
496 }
497
498 return AddClass(SearchClass);
499 }
500
501
507 int32 Num() const
508 {
509 int32 Count = 1;
510 for ( int32 i = 0; i < Children.Num(); i++ )
511 {
512 Count += Children[i]->Num();
513 }
514
515 return Count;
516 }
517
521 void Validate() const
522 {
523 if ( Parent == NULL )
524 {
525 // verify that we have a parent - only the UObject class is allowed to have no parents
526 check(Class==UObject::StaticClass());
527 }
528
529 // if our parent is Object, verify that none of object's children could have been our parent
530 else if ( Parent->GetClass() == UObject::StaticClass() )
531 {
532 TArray<const FClassTree*> ChildClasses;
533 Parent->GetChildClasses(ChildClasses);
534
535 for ( int32 i = 0; i < ChildClasses.Num(); i++ )
536 {
537 // skip ourselves
538 if ( ChildClasses[i] != this )
539 {
540 UClass* OtherClass = ChildClasses[i]->GetClass();
542
543 // verify that the other class is not a parent of this one
544 check(!Class->IsChildOf(OtherClass));
545 }
546 }
547 }
548 else
549 {
550 // otherwise, our parent node should be the node for our class's parent class
551 check(Class->GetSuperClass() == Parent->GetClass());
552 }
553 }
554
560 FClassTree( UClass* BaseClass ) : Class(BaseClass), Parent(NULL)
561 {
562 check(Class);
563 }
564
569 {
570 Class = NULL;
571
572 // clear the memory allocated by this branch
573 for ( int32 i = 0; i < Children.Num(); i++ )
574 {
575 FClassTree* p = Children[i];
576 if ( p != NULL )
577 {
578 delete p;
579 }
580 }
581
582 Children.Empty();
583 }
584
585 void DumpClassTree( int32 IndentCount, FOutputDevice& Ar )
586 {
587 Ar.Logf(TEXT("%s%s"), FCString::Spc(IndentCount), *Class->GetName());
588 for ( int32 ChildIndex = 0; ChildIndex < Children.Num(); ChildIndex++ )
589 {
590 FClassTree* ChildNode = Children[ChildIndex];
591 ChildNode->DumpClassTree(IndentCount + 2, Ar);
592 }
593 }
594
601 {
602 return Children.Num();
603 }
604
606 {
607 return Children[Index];
608 }
609};
#define NULL
Definition oodle2base.h:134
#define check(expr)
Definition AssertionMacros.h:314
EClassFlagMatchType
Definition ClassTree.h:17
@ MATCH_Any
Definition ClassTree.h:19
@ MATCH_All
Definition ClassTree.h:22
@ INDEX_NONE
Definition CoreMiscDefines.h:150
#define TEXT(x)
Definition Platform.h:1272
FPlatformTypes::int32 int32
A 32-bit signed integer.
Definition Platform.h:1125
#define UE_FORCEINLINE_HINT
Definition Platform.h:723
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
Definition ClassTree.h:31
const FClassTree * GetRootNode() const
Definition ClassTree.h:406
FClassTree * GetRootNode()
Definition ClassTree.h:396
void GetChildClasses(TArray< const FClassTree * > &ChildClasses, bool bRecurse=false) const
Definition ClassTree.h:311
void GetChildClasses(TArray< UClass * > &ChildClasses, const Comparator &Mask, bool bRecurse=false) const
Definition ClassTree.h:342
void DumpClassTree(int32 IndentCount, FOutputDevice &Ar)
Definition ClassTree.h:585
FClassTree * GenerateMaskedClassTree(const Comparator &Mask) const
Definition ClassTree.h:373
int32 Num() const
Definition ClassTree.h:507
FClassTree * GetNode(UClass *SearchClass)
Definition ClassTree.h:420
UE_FORCEINLINE_HINT int32 NumChildren() const
Definition ClassTree.h:600
void Validate() const
Definition ClassTree.h:521
void PopulateTree()
Definition ClassTree.h:219
~FClassTree()
Definition ClassTree.h:568
UClass * GetClass() const
Definition ClassTree.h:256
const FClassTree * FindNode(UClass *SearchClass) const
Definition ClassTree.h:432
FClassTree(UClass *BaseClass)
Definition ClassTree.h:560
UE_FORCEINLINE_HINT const FClassTree * GetChild(int32 Index) const
Definition ClassTree.h:605
bool AddClass(UClass *ChildClass)
Definition ClassTree.h:241
void GetChildClasses(TArray< FClassTree * > &ChildClasses, bool bRecurse=false)
Definition ClassTree.h:283
bool ChangeParentClass(UClass *SearchClass, UClass *InNewParentClass=NULL)
Definition ClassTree.h:457
Definition OutputDevice.h:133
void Logf(const FmtType &Fmt)
Definition OutputDevice.h:234
Definition Array.h:670
UE_REWRITE SizeType Num() const
Definition Array.h:1144
UE_NODEBUG UE_FORCEINLINE_HINT SizeType Add(ElementType &&Item)
Definition Array.h:2696
void Empty(SizeType Slack=0)
Definition Array.h:2273
Definition List.h:439
Definition UObjectIterator.h:257
Definition Class.h:3793
UClass * GetSuperClass() const
Definition Class.h:4352
FORCEINLINE UClass * GetClass() const
Definition UObjectBase.h:217
U16 Index
Definition radfft.cpp:71
static UE_FORCEINLINE_HINT int32 Stricmp(const CharType *String1, const CharType *String2)
Definition CString.h:1030
static const CharType * Spc(int32 NumSpaces)
Definition CString.h:624