UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
NodeHierarchy.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
5#include "CoreMinimal.h"
7#include "Constraint.h"
8#include "Algo/Transform.h"
9#include "NodeHierarchy.generated.h"
10
12USTRUCT()
14{
16
19 , ParentName(NAME_None)
20 {}
21
22 FNodeObject(const FName& InName, const FName& InParentName)
23 : Name(InName)
24 , ParentName(InParentName)
25 {}
26
28 UPROPERTY()
30
32 UPROPERTY()
33 FName ParentName;
34};
35
37USTRUCT()
39{
41
42
43 UPROPERTY()
45
47 UPROPERTY()
48 TArray<FTransform> Transforms;
49
51 UPROPERTY()
52 TMap<FName, int32> NodeNameToIndexMapping;
53
54public:
55 const FTransform& GetTransform(int32 Index) const
56 {
57 return Transforms[Index];
58 }
59
61 {
62 return Transforms[Index];
63 }
64
65 void SetTransform(int32 Index, const FTransform& NewTransform)
66 {
67 Transforms[Index] = NewTransform;
68 Transforms[Index].NormalizeRotation();
69 }
70
72 {
73 return GetNodeIndex(Nodes[Index].ParentName);
74 }
75
77 {
78 return Nodes[Index].ParentName;
79 }
80
82 {
83 Nodes[Index].ParentName = NewParent;
84 }
85
86 int32 GetNodeIndex(const FName& NodeName) const
87 {
88 const int32* NodeIndex = NodeNameToIndexMapping.Find(NodeName);
89 return (NodeIndex)? *NodeIndex : INDEX_NONE;
90 }
91
93 {
94 return Nodes[Index].Name;
95 }
96
98 {
99 FName OldName = Nodes[Index].Name;
100 Nodes[Index].Name = NewNodeName;
101
102 // now find all the nodes with this as parent
103 for (int32 NodeIndex = 0; NodeIndex < Nodes.Num(); ++NodeIndex)
104 {
105 if (Nodes[NodeIndex].ParentName == OldName)
106 {
107 Nodes[NodeIndex].ParentName = NewNodeName;
108 }
109 }
110
111 BuildNodeNameToIndexMapping();
112 }
113
115 {
116 // already exists
117 if (NodeNameToIndexMapping.Contains(InNodeName))
118 {
119 return INDEX_NONE;
120 }
121
122 // if parent name is set, but we don't have it yet?
123 if (InParentName != NAME_None && !NodeNameToIndexMapping.Contains(InParentName))
124 {
125 // warn user?
126 }
127
128 check(Nodes.Num() == Transforms.Num());
129
130 int32 NewIndex = Nodes.Add(FNodeObject(InNodeName, InParentName));
131 Transforms.Add(InTransform);
132
133 BuildNodeNameToIndexMapping();
134
135 return NewIndex;
136 }
137
138 void Empty(int32 Size = 0)
139 {
140 Nodes.Empty(Size);
141 Transforms.Empty(Size);
142 NodeNameToIndexMapping.Reset();
143 }
144
146 {
147 Empty(Size);
148 }
149
151 int32 Num() const
152 {
153 return Nodes.Num();
154 }
155
157 {
158 return Nodes.IsValidIndex(Index);
159 }
160
162 {
163 int32* NodeIndex = NodeNameToIndexMapping.Find(InNodeName);
165 if (NodeIndex)
166 {
167 check(Nodes.Num() == Transforms.Num());
168
169 Nodes.RemoveAt(*NodeIndex);
170 Transforms.RemoveAt(*NodeIndex);
171 ReturnIndex = *NodeIndex;
172 }
173 else
174 {
175 // does not exists
176 }
177
178 BuildNodeNameToIndexMapping();
179
180 return ReturnIndex;
181 }
182
184 {
185 NodeNameToIndexMapping.Empty();
186
187 for (int32 NodeIndex = 0; NodeIndex < Nodes.Num(); ++NodeIndex)
188 {
189 int32& Index = NodeNameToIndexMapping.Add(Nodes[NodeIndex].Name);
190 Index = NodeIndex;
191 }
192
193 check(Nodes.Num() == NodeNameToIndexMapping.Num());
194 }
195};
196
197USTRUCT()
199{
201
202protected:
203 UPROPERTY()
205
206public:
208
209 const FNodeHierarchyData& GetHierarchy() const { return Hierarchy; }
210 const TArray<FTransform>& GetTransforms() const { return Hierarchy.Transforms; }
212 const TArray<FNodeObject>& GetNodes() const { return Hierarchy.Nodes; }
213
214 template<typename DataType>
215 const DataType& GetNodeData(int32 Index) const { return *reinterpret_cast<const DataType*>(GetUserDataImpl(Index)); }
216
217 template<typename DataType>
218 DataType& GetNodeData(int32 Index) { return *reinterpret_cast<DataType*>(GetUserDataImpl(Index)); }
219
220 // it's up to your hierarchy to decide what to do with this
221 virtual const FTransform& GetLocalTransform(int32 Index) const PURE_VIRTUAL(FNodeHierarchyWithUserData::GetLocalTransform, return Hierarchy.Transforms[Index];)
222 virtual const FTransform& GetGlobalTransform(int32 Index) const PURE_VIRTUAL(FNodeHierarchyWithUserData::GetGlobalTransform, return Hierarchy.Transforms[Index];)
223 virtual FTransform& GetLocalTransform(int32 Index) PURE_VIRTUAL(FNodeHierarchyWithUserData::GetLocalTransform, return Hierarchy.Transforms[Index];)
224 virtual FTransform& GetGlobalTransform(int32 Index) PURE_VIRTUAL(FNodeHierarchyWithUserData::GetGlobalTransform, return Hierarchy.Transforms[Index];)
225 virtual void SetLocalTransform(int32 Index, const FTransform& NewTransform) { }
226 virtual void SetGlobalTransform(int32 Index, const FTransform& NewTransform) { }
227
228 // get all list of children
230 {
232 FName NodeName = Hierarchy.Nodes[Index].Name;
233 for (int32 NodeIndex = 0; NodeIndex < Hierarchy.Nodes.Num(); ++NodeIndex)
234 {
235 if (Hierarchy.Nodes[NodeIndex].ParentName == NodeName)
236 {
237 ChildrenNames.Add(Hierarchy.Nodes[NodeIndex].Name);
238 }
239 }
240
241 return ChildrenNames;
242 }
243
245 {
246 int32 Index = GetNodeIndex(NodeName);
247 if (IsValidIndex(Index))
248 {
249 return GetLocalTransform(Index);
250 }
251
253 }
254
256 {
257 int32 Index = GetNodeIndex(NodeName);
258 if (IsValidIndex(Index))
259 {
260 return GetGlobalTransform(Index);
261 }
262
264 }
265
266 void SetLocalTransformByName(const FName& NodeName, const FTransform& NewTransform)
267 {
268 int32 Index = GetNodeIndex(NodeName);
269 if (IsValidIndex(Index))
270 {
271 SetLocalTransform(Index, NewTransform);
272 }
273 }
274
275 void SetGlobalTransformByName(const FName& NodeName, const FTransform& NewTransform)
276 {
277 int32 Index = GetNodeIndex(NodeName);
278 if (IsValidIndex(Index))
279 {
280 SetGlobalTransform(Index, NewTransform);
281 }
282 }
283 // should initialize all transient data for fast look up
284 virtual void Initialize()
285 {
286 Hierarchy.BuildNodeNameToIndexMapping();
287 }
288
290 {
291 return Hierarchy.GetParentIndex(Index);
292 }
293
295 {
296 return Hierarchy.GetParentName(Index);
297 }
298
299 FName GetParentName(const FName& NodeName) const
300 {
301 int32 Index = GetNodeIndex(NodeName);
302 if (IsValidIndex(Index))
303 {
304 return Hierarchy.GetParentName(Index);
305 }
306
307 return NAME_None;
308 }
309
311 {
312 // if no parent or if exist - reject typos
313 if (NewParent == NAME_None || Contains(NewParent))
314 {
315 Hierarchy.SetParentName(Index, NewParent);
316 }
317 }
318
320 {
321 return Hierarchy.GetNodeIndex(InNodeName);
322 }
323
325 {
326 return Hierarchy.GetNodeName(Index);
327 }
328
329 void SetNodeName(int32 Index, const FName& NewNode)
330 {
331 Hierarchy.SetNodeName(Index, NewNode);
332 }
333
335 {
336 check(!HasUserData());
338 }
339
340 template<typename DataType>
341 int32 Add(const FName& InNodeName, const FName& InParentName, const FTransform& InTransform, const DataType& InNodeData)
342 {
344 if (Index != INDEX_NONE && HasUserData())
345 {
346 int32 UserDataIndex = AddUserDataImpl(&InNodeData);
347
349 check(Hierarchy.Nodes.Num() == Hierarchy.Transforms.Num() && Hierarchy.Transforms.Num() == GetNumUserData());
350 }
351
352 return Index;
353 }
354
356 {
358 if (HasUserData())
359 {
361 {
362 RemoveUserData(RemovedIndex);
363 }
364
365 check(Hierarchy.Nodes.Num() == Hierarchy.Transforms.Num() && Hierarchy.Transforms.Num() == GetNumUserData());
366 }
367 }
368
369 void Empty(int32 Size = 0)
370 {
371 Hierarchy.Empty(Size);
372 if (HasUserData())
373 {
374 EmptyUserData(Size);
375
376 check(Hierarchy.Nodes.Num() == Hierarchy.Transforms.Num() && Hierarchy.Transforms.Num() == GetNumUserData());
377 }
378 }
379
380 int32 GetNum() const
381 {
382 return Hierarchy.Num();
383 }
384
386 {
387 return Hierarchy.IsValidIndex(Index);
388 }
389
390 bool Contains(const FName InNodeName) const
391 {
392 return GetNodeIndex(InNodeName) != INDEX_NONE;
393 }
394
395protected:
397 virtual const void* GetUserDataImpl(int32 Index) const { return nullptr; }
398 virtual void* GetUserDataImpl(int32 Index) { return nullptr; }
399 virtual int32 AddUserDataImpl(const void* InData) { return INDEX_NONE; }
400 virtual int32 GetNumUserData() const { return 0; }
401 virtual void EmptyUserData(int32 Size = 0) {}
402 virtual void RemoveUserData(int32 Index) {}
403 virtual bool HasUserData() const { return false; }
404};
405
406template<>
408{
409 enum
410 {
412 };
413};
#define check(expr)
Definition AssertionMacros.h:314
@ INDEX_NONE
Definition CoreMiscDefines.h:150
#define PURE_VIRTUAL(func,...)
Definition CoreMiscDefines.h:103
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
#define UPROPERTY(...)
UObject definition macros.
Definition ObjectMacros.h:744
#define GENERATED_BODY(...)
Definition ObjectMacros.h:765
#define USTRUCT(...)
Definition ObjectMacros.h:746
uint32 Size
Definition VulkanMemory.cpp:4034
Definition NameTypes.h:617
Definition Array.h:670
Definition UnrealString.h.inl:34
U16 Index
Definition radfft.cpp:71
Definition NodeHierarchy.h:39
int32 GetParentIndex(int32 Index) const
Definition NodeHierarchy.h:71
int32 Num() const
Definition NodeHierarchy.h:151
FName GetParentName(int32 Index) const
Definition NodeHierarchy.h:76
void SetParentName(int32 Index, FName NewParent)
Definition NodeHierarchy.h:81
void Allocate(int32 Size)
Definition NodeHierarchy.h:145
int32 Add(const FName &InNodeName, const FName &InParentName, const FTransform &InTransform)
Definition NodeHierarchy.h:114
FTransform & GetTransform(int32 Index)
Definition NodeHierarchy.h:60
FName GetNodeName(int32 Index) const
Definition NodeHierarchy.h:92
void BuildNodeNameToIndexMapping()
Definition NodeHierarchy.h:183
int32 GetNodeIndex(const FName &NodeName) const
Definition NodeHierarchy.h:86
void Empty(int32 Size=0)
Definition NodeHierarchy.h:138
void SetTransform(int32 Index, const FTransform &NewTransform)
Definition NodeHierarchy.h:65
int32 Remove(const FName &InNodeName)
Definition NodeHierarchy.h:161
void SetNodeName(int32 Index, const FName &NewNodeName)
Definition NodeHierarchy.h:97
bool IsValidIndex(int32 Index) const
Definition NodeHierarchy.h:156
Definition NodeHierarchy.h:199
FName GetParentName(int32 Index) const
Definition NodeHierarchy.h:294
virtual void EmptyUserData(int32 Size=0)
Definition NodeHierarchy.h:401
virtual void SetGlobalTransform(int32 Index, const FTransform &NewTransform)
Definition NodeHierarchy.h:226
int32 Add(const FName &InNodeName, const FName &InParentName, const FTransform &InTransform)
Definition NodeHierarchy.h:334
virtual void RemoveUserData(int32 Index)
Definition NodeHierarchy.h:402
virtual void * GetUserDataImpl(int32 Index)
Definition NodeHierarchy.h:398
bool Contains(const FName InNodeName) const
Definition NodeHierarchy.h:390
virtual void Initialize()
Definition NodeHierarchy.h:284
int32 Add(const FName &InNodeName, const FName &InParentName, const FTransform &InTransform, const DataType &InNodeData)
Definition NodeHierarchy.h:341
TArray< FTransform > & GetTransforms()
Definition NodeHierarchy.h:211
const TArray< FNodeObject > & GetNodes() const
Definition NodeHierarchy.h:212
int32 GetParentIndex(int32 Index) const
Definition NodeHierarchy.h:289
void SetParentName(int32 Index, FName NewParent)
Definition NodeHierarchy.h:310
FName GetParentName(const FName &NodeName) const
Definition NodeHierarchy.h:299
int32 GetNum() const
Definition NodeHierarchy.h:380
FTransform GetGlobalTransformByName(const FName &NodeName) const
Definition NodeHierarchy.h:255
void SetLocalTransformByName(const FName &NodeName, const FTransform &NewTransform)
Definition NodeHierarchy.h:266
DataType & GetNodeData(int32 Index)
Definition NodeHierarchy.h:218
FName GetNodeName(int32 Index) const
Definition NodeHierarchy.h:324
virtual int32 AddUserDataImpl(const void *InData)
Definition NodeHierarchy.h:399
virtual const FTransform &virtual GetLocalTransform(int32 Index) const PURE_VIRTUAL(FNodeHierarchyWithUserData const FTransform &virtual GetGlobalTransform(int32 Index) const PURE_VIRTUAL(FNodeHierarchyWithUserData FTransform &virtual GetLocalTransform(int32 Index) PURE_VIRTUAL(FNodeHierarchyWithUserData FTransform &virtual GetGlobalTransform(int32 Index) PURE_VIRTUAL(FNodeHierarchyWithUserData void SetLocalTransform(int32 Index, const FTransform &NewTransform)
Definition NodeHierarchy.h:225
virtual bool HasUserData() const
Definition NodeHierarchy.h:403
void Remove(const FName &InNodeName)
Definition NodeHierarchy.h:355
const FNodeHierarchyData & GetHierarchy() const
Definition NodeHierarchy.h:209
int32 GetNodeIndex(const FName &InNodeName) const
Definition NodeHierarchy.h:319
void Empty(int32 Size=0)
Definition NodeHierarchy.h:369
void SetNodeName(int32 Index, const FName &NewNode)
Definition NodeHierarchy.h:329
const DataType & GetNodeData(int32 Index) const
Definition NodeHierarchy.h:215
FTransform GetLocalTransformByName(const FName &NodeName) const
Definition NodeHierarchy.h:244
const TArray< FTransform > & GetTransforms() const
Definition NodeHierarchy.h:210
bool IsValidIndex(int32 Index) const
Definition NodeHierarchy.h:385
void SetGlobalTransformByName(const FName &NodeName, const FTransform &NewTransform)
Definition NodeHierarchy.h:275
virtual const void * GetUserDataImpl(int32 Index) const
Definition NodeHierarchy.h:397
TArray< FName > GetChildren(int32 Index) const
Definition NodeHierarchy.h:229
virtual int32 GetNumUserData() const
Definition NodeHierarchy.h:400
Definition NodeHierarchy.h:14
FNodeObject(const FName &InName, const FName &InParentName)
Definition NodeHierarchy.h:22
Definition StructOpsTypeTraits.h:11
@ WithPureVirtual
Definition StructOpsTypeTraits.h:33
Definition StructOpsTypeTraits.h:46
static CORE_API const TTransform< double > Identity
Definition TransformNonVectorized.h:58
void NormalizeRotation()
Definition TransformNonVectorized.h:1057