UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
FieldPath.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3/*=============================================================================
4 SoftObjectPtr.h: Pointer to UObject asset, keeps extra information so that it is works even if the asset is not in memory
5=============================================================================*/
6
7#pragma once
8
9#include "Containers/Array.h"
10#include "Containers/Map.h"
12#include "CoreTypes.h"
15#include "Templates/Requires.h"
16#include "Templates/TypeHash.h"
18#include "UObject/Field.h"
19#include "UObject/NameTypes.h"
23
24#include <type_traits>
25
26class FArchive;
27class FLinkerLoad;
28class UField;
29class UStruct;
30struct FUObjectItem;
31template <typename T> struct TIsPODType;
32template <typename T> struct TIsWeakPointerType;
33template <typename T> struct TIsZeroConstructType;
34
36{
37 friend struct FGCInternals;
38
39 // TWeakFieldPtr needs access to ClearCachedField
40 template<class T>
41 friend struct TWeakFieldPtr;
42
43 // FFieldPathProperty needs access to ConvertFromFullPath
44 friend class FFieldPathProperty;
45
46protected:
47
48 /* Determines the behavior when resolving stored path */
54
56 mutable FField* ResolvedField = nullptr;
57#if WITH_EDITORONLY_DATA
59 mutable FFieldClass* InitialFieldClass = nullptr;
61 mutable int32 FieldPathSerialNumber = 0;
62#endif
65
68
69 inline bool NeedsResolving() const
70 {
71 if (ResolvedField)
72 {
73#if WITH_EDITORONLY_DATA
75 // In uncooked builds we also need to check if the serial number on the owner struct is identical
76 // It will change if the struct has been recompiled or its properties have been destroyed
78 {
79 return false;
80 }
81#else
82 // The assumption is that if we already resolved a field and its owner is still valid, there's no need to resolve again
83 return !ResolvedOwner.IsValid();
84#endif // WITH_EDITORONLY_DATA
85 }
86 return true;
87 }
88
90 inline void ClearCachedField() const
91 {
92 ResolvedField = nullptr;
93#if WITH_EDITORONLY_DATA
94 InitialFieldClass = nullptr;
96#endif // WITH_EDITORONLY_DATA
97 }
98
99private:
100
101#if WITH_EDITORONLY_DATA
106#endif
107
109 UE_FORCEINLINE_HINT FUObjectItem* GetResolvedOwnerItemInternal()
110 {
111 return ResolvedOwner.Internal_GetObjectItem();
112 }
113 inline void ClearCachedFieldInternal()
114 {
115 ResolvedField = nullptr;
117 }
118
126
127
133 COREUOBJECT_API UStruct* TryToResolveOwnerFromLinker(FLinkerLoad* InLinker) const;
134
135
141 COREUOBJECT_API UStruct* ConvertFromFullPath(FLinkerLoad* InLinker);
142
143public:
144
145 FFieldPath() = default;
146
151
152#if WITH_EDITORONLY_DATA
154#endif
155
158
161
162#if WITH_EDITORONLY_DATA
164#endif
165
173
180 {
185#endif // WITH_EDITORONLY_DATA
186 )
187 {
189#if WITH_EDITORONLY_DATA
191 {
193 }
195 check(Owner);
197#endif // WITH_EDITORONLY_DATA
198 }
199 else if (ResolvedField)
200 {
201 // In case this field has been previously resolved, clear the owner as well as it's impossible the original field
202 // will ever come back (it's most likely been deleted) and we don't want to resolve to a newly created one even if its name and class match
204 ResolvedField = nullptr;
205 }
206 }
207
222
227 inline bool IsPathToFieldEmpty() const
228 {
229 return !Path.Num();
230 }
231
236 inline bool IsStale() const
237 {
239#if WITH_EDITORONLY_DATA
241#endif // WITH_EDITORONLY_DATA
242 );
243 }
244
248 inline void Reset()
249 {
252 Path.Empty();
253 }
254
256 {
257 return ResolvedOwner == InOther.ResolvedOwner && Path == InOther.Path;
258 }
259
261 {
262 return ResolvedOwner != InOther.ResolvedOwner || Path != InOther.Path;
263 }
264
265 COREUOBJECT_API FString ToString() const;
266
268
271 {
272 uint32 HashValue = 0;
273 for (const FName& PathSegment : InPropertyPath.Path)
274 {
276 }
277 return HashValue;
278 }
279};
280
281template<class PropertyType>
282struct TFieldPath : public FFieldPath
283{
284private:
285
286 // These exists only to disambiguate the two constructors below
287 enum EDummy1 { Dummy1 };
288
289public:
291 {}
293 {
294 // First refresh the serial number from the other path
295 Other.Get();
296 // Now that the Other path is refreshed, we can copy from it
297 FFieldPath::operator=(Other);
298 }
300 {
301 // First refresh the serial number from the other path
302 Other.Get();
303 // Now that the Other path is refreshed, we can copy from it
304 FFieldPath::operator=(Other);
305 return *this;
306 }
307
315
319 inline TFieldPath(const TCHAR* InPath)
320 : FFieldPath()
321 {
323 }
324
325#if WITH_EDITORONLY_DATA
327 : FFieldPath(InField, PropertyType::StaticClass()->GetFName())
328 {
329 // This static assert is in here rather than in the body of the class because we want
330 // to be able to define TWeakFieldPtr<UUndefinedClass>.
331 static_assert(std::is_convertible_v<PropertyType*, const volatile FField*>, "TFieldPath can only be constructed with FField types");
332 }
333#endif
334
339 template <
340 typename OtherPropertyType
341 UE_REQUIRES(std::is_convertible_v<OtherPropertyType*, PropertyType*>)
342 >
343 inline TFieldPath(OtherPropertyType* InProperty, EDummy1 = Dummy1)
344 : FFieldPath((FField*)CastField<PropertyType>(InProperty))
345 {
346 // This static assert is in here rather than in the body of the class because we want
347 // to be able to define TFieldPath<UUndefinedClass>.
348 static_assert(std::is_convertible_v<PropertyType*, const volatile FField*>, "TFieldPath can only be constructed with FField types");
349 }
350
355 template <
356 typename OtherPropertyType
357 UE_REQUIRES(std::is_convertible_v<OtherPropertyType*, PropertyType*>)
358 >
361 {
362 // This static assert is in here rather than in the body of the class because we want
363 // to be able to define TFieldPath<UUndefinedClass>.
364 static_assert(std::is_convertible_v<PropertyType*, const volatile FField*>, "TFieldPath can only be constructed with FField types");
365 }
366
371 template <
372 typename OtherPropertyType
373 UE_REQUIRES(std::is_convertible_v<OtherPropertyType*, PropertyType*>)
374 >
376 {
377 // This (FField*) cast is effectively a const_cast, as we've already validated the convertibility in the
378 // constraint, and that PropertyType is an FField type in the constructors.
381 }
382
387 template <
388 typename OtherPropertyType
389 UE_REQUIRES(std::is_convertible_v<OtherPropertyType*, PropertyType*>)
390 >
392 {
393 // First make sure the Other path has the serial number up to date, otherwise we'll keep having to
394 // reevealuate this path because it gets the serial number copied from the Other path
395 Other.Get();
396 // Now that the Other path is refreshed, we can copy from it
397 FFieldPath::operator=(Other);
398 }
399
405 UE_FORCEINLINE_HINT PropertyType* Get(UStruct* InCurrentStruct = nullptr) const
406 {
407 return (PropertyType*)GetTyped(PropertyType::StaticClass(), InCurrentStruct);
408 }
409
411 {
413 ResolveField(PropertyType::StaticClass(), InCurrentStruct, FFieldPath::UseStructAlways);
414 return static_cast<PropertyType*>(ResolvedField);
415 }
416
420 UE_FORCEINLINE_HINT PropertyType* operator*() const
421 {
422 return Get();
423 }
424
428 UE_FORCEINLINE_HINT PropertyType* operator->() const
429 {
430 return Get();
431 }
432};
433
439template <typename LhsType, typename RhsType>
441 -> decltype((LhsType*)nullptr == (RhsType*)nullptr)
442{
443 return *(const FFieldPath*)&Lhs == *(const FFieldPath*)&Rhs;
444}
445
451template <typename LhsType, typename RhsType>
453 -> decltype((LhsType*)nullptr == Rhs)
454{
455 return Lhs.Get() == Rhs;
456}
457
463template <typename LhsType, typename RhsType>
465 -> decltype(Lhs == (RhsType*)nullptr)
466{
467 return Lhs == Rhs.Get();
468}
469
474template <typename LhsType>
479
484template <typename RhsType>
486{
487 return !Rhs.Get();
488}
489
490#if !PLATFORM_COMPILER_HAS_GENERATED_COMPARISON_OPERATORS
496template <typename LhsType, typename RhsType>
498 -> decltype((LhsType*)nullptr != (RhsType*)nullptr)
499{
500 return !(Lhs == Rhs);
501}
502
508template <typename LhsType, typename RhsType>
510 -> decltype((LhsType*)nullptr != Rhs)
511{
512 return !(Lhs == Rhs);
513}
514
520template <typename LhsType, typename RhsType>
522 -> decltype(Lhs != (RhsType*)nullptr)
523{
524 return !(Lhs == Rhs);
525}
526
531template <typename LhsType>
533{
534 return !(Lhs == nullptr);
535}
536
541template <typename RhsType>
543{
544 return !(nullptr == Rhs);
545}
546#endif
547
548// Helper function which deduces the type of the initializer
549template <typename PropertyType>
554
555
556template<class T> struct TIsPODType<TFieldPath<T> > { enum { Value = true }; };
557template<class T> struct TIsZeroConstructType<TFieldPath<T> > { enum { Value = true }; };
558template<class T> struct TIsWeakPointerType<TFieldPath<T> > { enum { Value = true }; };
559
560
564template <typename KeyType, typename ValueType, bool bInAllowDuplicateKeys = false>
565struct TPropertyPathMapKeyFuncs : public TDefaultMapKeyFuncs<KeyType, ValueType, bInAllowDuplicateKeys>
566{
568
570 {
571 return A == B;
572 }
573
575 {
576 return GetTypeHash(Key);
577 }
578};
#define check(expr)
Definition AssertionMacros.h:314
#define WITH_EDITORONLY_DATA
Definition CoreMiscDefines.h:24
UE_FORCEINLINE_HINT FieldType * CastField(FField *Src)
Definition Field.h:1106
FPlatformTypes::TYPE_OF_NULLPTR TYPE_OF_NULLPTR
The type of the C++ nullptr keyword.
Definition Platform.h:1157
FPlatformTypes::TCHAR TCHAR
Either ANSICHAR or WIDECHAR, depending on whether the platform supports wide characters or the requir...
Definition Platform.h:1135
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
UE_FORCEINLINE_HINT auto operator==(const TFieldPath< LhsType > &Lhs, const TFieldPath< LhsType > &Rhs) -> decltype((LhsType *) nullptr==(RhsType *) nullptr)
Definition FieldPath.h:440
UE_FORCEINLINE_HINT auto operator!=(const TFieldPath< LhsType > &Lhs, const TFieldPath< LhsType > &Rhs) -> decltype((LhsType *) nullptr !=(RhsType *) nullptr)
Definition FieldPath.h:497
UE_FORCEINLINE_HINT TFieldPath< PropertyType > MakePropertyPath(PropertyType *Ptr)
Definition FieldPath.h:550
UClass * StaticClass()
Definition ReflectedTypeAccessors.h:13
#define UE_REQUIRES(...)
Definition Requires.h:86
constexpr uint32 HashCombine(uint32 A, uint32 C)
Definition TypeHash.h:36
uint32_t uint32
Definition binka_ue_file_header.h:6
Definition Archive.h:1208
Definition Field.h:66
Definition FieldPathProperty.h:25
Definition Field.h:556
static COREUOBJECT_API FFieldClass * StaticClass()
Definition Field.cpp:293
FFieldClass * GetClass() const
Definition Field.h:722
Definition LinkerLoad.h:124
Definition NameTypes.h:617
Definition Array.h:670
UE_REWRITE SizeType Num() const
Definition Array.h:1144
void Empty(SizeType Slack=0)
Definition Array.h:2273
Definition Class.h:181
Definition Class.h:480
Definition FieldPath.h:36
friend uint32 GetTypeHash(const FFieldPath &InPropertyPath)
Definition FieldPath.h:270
void Reset()
Definition FieldPath.h:248
TWeakObjectPtr< UStruct > ResolvedOwner
Definition FieldPath.h:64
EPathResolveType
Definition FieldPath.h:50
@ UseStructAlways
Definition FieldPath.h:52
@ UseStructIfOuterNotFound
Definition FieldPath.h:51
TArray< FName > Path
Definition FieldPath.h:67
COREUOBJECT_API void Generate(FField *InField)
Definition FieldPath.cpp:78
bool IsStale() const
Definition FieldPath.h:236
UE_FORCEINLINE_HINT bool operator==(const FFieldPath &InOther) const
Definition FieldPath.h:255
bool IsPathToFieldEmpty() const
Definition FieldPath.h:227
UE_FORCEINLINE_HINT bool operator!=(const FFieldPath &InOther) const
Definition FieldPath.h:260
COREUOBJECT_API friend FArchive & operator<<(FArchive &Ar, FFieldPath &InOutPropertyPath)
Definition FieldPath.cpp:316
COREUOBJECT_API FString ToString() const
Definition FieldPath.cpp:291
FFieldPath()=default
bool NeedsResolving() const
Definition FieldPath.h:69
void ResolveField(FFieldClass *ExpectedClass=FField::StaticClass(), UStruct *InCurrentStruct=nullptr, EPathResolveType InResolveType=FFieldPath::UseStructIfOuterNotFound) const
Definition FieldPath.h:179
FFieldPath(FField *InField)
Definition FieldPath.h:147
COREUOBJECT_API FField * TryToResolvePath(UStruct *InCurrentStruct, EPathResolveType InResolveType=FFieldPath::UseStructIfOuterNotFound) const
Definition FieldPath.cpp:268
FField * GetTyped(FFieldClass *ExpectedType, UStruct *InCurrentStruct=nullptr) const
Definition FieldPath.h:214
FField * ResolvedField
Definition FieldPath.h:56
void ClearCachedField() const
Definition FieldPath.h:90
Definition FastReferenceCollector.h:61
Definition UObjectArray.h:50
Definition Map.h:77
TTypeTraits< KeyType >::ConstPointerType KeyInitType
Definition Map.h:78
Definition FieldPath.h:283
PropertyType * ResolveWithRenamedStructPackage(UStruct *InCurrentStruct)
Definition FieldPath.h:410
void operator=(const TFieldPath< OtherPropertyType > &Other)
Definition FieldPath.h:391
TFieldPath(const TFieldPath< OtherPropertyType > &Other)
Definition FieldPath.h:359
TFieldPath & operator=(const TFieldPath &Other)
Definition FieldPath.h:299
TFieldPath(const TCHAR *InPath)
Definition FieldPath.h:319
UE_FORCEINLINE_HINT PropertyType * Get(UStruct *InCurrentStruct=nullptr) const
Definition FieldPath.h:405
UE_FORCEINLINE_HINT TFieldPath(TYPE_OF_NULLPTR)
Definition FieldPath.h:311
UE_FORCEINLINE_HINT PropertyType * operator->() const
Definition FieldPath.h:428
void operator=(OtherPropertyType *InProperty)
Definition FieldPath.h:375
UE_FORCEINLINE_HINT PropertyType * operator*() const
Definition FieldPath.h:420
TFieldPath(const TFieldPath &Other)
Definition FieldPath.h:292
TFieldPath(OtherPropertyType *InProperty, EDummy1=Dummy1)
Definition FieldPath.h:343
TFieldPath()
Definition FieldPath.h:290
Definition IsPODType.h:12
@ Value
Definition IsPODType.h:13
Definition UnrealTypeTraits.h:181
@ Value
Definition UnrealTypeTraits.h:182
Definition UnrealTypeTraits.h:172
Definition FieldPath.h:566
static UE_FORCEINLINE_HINT uint32 GetKeyHash(KeyInitType Key)
Definition FieldPath.h:574
TDefaultMapKeyFuncs< KeyType, ValueType, bInAllowDuplicateKeys >::KeyInitType KeyInitType
Definition FieldPath.h:567
static UE_FORCEINLINE_HINT bool Matches(KeyInitType A, KeyInitType B)
Definition FieldPath.h:569
Definition WeakFieldPtr.h:65
Definition WeakObjectPtrTemplates.h:25
FORCEINLINE void Reset()
Definition WeakObjectPtrTemplates.h:92
FORCEINLINE T * Get(bool bEvenIfPendingKill) const
Definition WeakObjectPtrTemplates.h:132
FORCEINLINE bool IsValid(bool bEvenIfPendingKill, bool bThreadsafeTest=false) const
Definition WeakObjectPtrTemplates.h:232