A Demo Project for the UnrealEngineSDK
Loading...
Searching...
No Matches
NYReflectionHelper.h
Go to the documentation of this file.
1// Copyright Csaba Molnar, Daniel Butum. All Rights Reserved.
2#pragma once
3
4// Protect against inclusion in multiple projects
5#ifndef NY_REFLECTION_HELPER
6#define NY_REFLECTION_HELPER
7
8#include "CoreMinimal.h"
9#include "NYReflectionTypes.h"
10
11DEFINE_LOG_CATEGORY_STATIC(LogDlgSystemReflectionHelper, All, All)
12
13class DLGSYSTEM_API FNYReflectionHelper
14{
15public:
16
17#if ENGINE_MINOR_VERSION >= 25
18 // From 4.25 UProperties are different
19 template<typename FieldType>
20 FORCEINLINE static FieldType* CastProperty(FField* Src)
21 {
22 return Src && Src->HasAnyCastFlags(FieldType::StaticClassCastFlagsPrivate()) ? static_cast<FieldType*>(Src) : nullptr;
23 }
24 // Const Version
25 template<typename FieldType>
26 FORCEINLINE static const FieldType* CastProperty(const FField* Src)
27 {
28 return Src && Src->HasAnyCastFlags(FieldType::StaticClassCastFlagsPrivate()) ? static_cast<const FieldType*>(Src) : nullptr;
29 }
30
31 FORCEINLINE static FField* GetStructChildren(const UStruct* Struct)
32 {
33 return Struct ? Struct->ChildProperties : nullptr;
34 }
35
36 // the old removed engine function this code still uses a lot:
37 template <typename To, typename From>
38 static To* SmartCastProperty(From* Src)
39 {
40 To* Result = CastProperty<To>(Src);
41 if (Result == nullptr)
42 {
43 FNYArrayProperty* ArrayProp = CastProperty<FNYArrayProperty>(Src);
44 if (ArrayProp != nullptr)
45 {
46 Result = CastProperty<To>(ArrayProp->Inner);
47 }
48 }
49 return Result;
50 }
51
52#else
53 template <typename To, typename From>
54 FORCEINLINE static To* CastProperty(From* Src)
55 {
56 return TCastImpl<From, To>::DoCast(Src);
57 }
58 // Const Version
59 template <typename To, typename From>
60 FORCEINLINE static const To* CastProperty(const From* Src)
61 {
62 return CastProperty<To>(const_cast<From*>(Src));
63 }
64
65 FORCEINLINE static UField* GetStructChildren(const UStruct* Struct)
66 {
67 return Struct ? Struct->Children : nullptr;
68 }
69
70 // the old removed engine function this code still uses a lot:
71 template <typename To, typename From>
72 static To* SmartCastProperty(From* Src)
73 {
74 To* Result = dynamic_cast<To*>(Src);
75 if (Result == nullptr)
76 {
77 FNYArrayProperty* ArrayProp = dynamic_cast<FNYArrayProperty*>(Src);
78 if (ArrayProp != nullptr)
79 {
80 Result = dynamic_cast<To*>(ArrayProp->Inner);
81 }
82 }
83 return Result;
84 }
85#endif // ENGINE_MINOR_VERSION >= 25
86
87 // Attempts to get the property VariableName from Object
88 template <typename PropertyType, typename VariableType>
89 static VariableType GetVariable(const UObject* Object, FName VariableName)
90 {
91 if (!IsValid(Object))
92 {
93 UE_LOG(
94 LogDlgSystemReflectionHelper,
95 Error,
96 TEXT("Failed to get %s %s from Object that is null (not valid)"),
97 *PropertyType::StaticClass()->GetName(), *VariableName.ToString()
98 );
99 return VariableType{};
100 }
101
102 for (auto* Property = Object->GetClass()->PropertyLink; Property != nullptr; Property = Property->PropertyLinkNext)
103 {
104 const PropertyType* CastedProperty = CastProperty<PropertyType>(Property);
105 if (CastedProperty != nullptr && CastedProperty->GetFName() == VariableName)
106 {
107 return CastedProperty->GetPropertyValue_InContainer(Object, 0);
108 }
109 }
110
111 UE_LOG(
112 LogDlgSystemReflectionHelper,
113 Warning,
114 TEXT("Failed to get %s %s from %s - property not found!"),
115 *PropertyType::StaticClass()->GetName(), *VariableName.ToString(), *Object->GetName()
116 );
117 return VariableType{};
118 }
119
120 // Attempts to modify the property VariableName from Object
121 template <typename PropertyType, typename VariableType>
122 static void ModifyVariable(UObject* Object, FName VariableName, const VariableType Value, bool bDelta)
123 {
124 if (!IsValid(Object))
125 {
126 UE_LOG(
127 LogDlgSystemReflectionHelper,
128 Error,
129 TEXT("Failed to modify %s %s of Object that is null (not valid)"),
130 *PropertyType::StaticClass()->GetName(), *VariableName.ToString()
131 );
132 return;
133 }
134
135 // Set the variable
136 if (!bDelta)
137 {
138 SetVariable<PropertyType>(Object, VariableName, Value);
139 return;
140 }
141
142 // Modify the current variable
143 for (auto* Property = Object->GetClass()->PropertyLink; Property != nullptr; Property = Property->PropertyLinkNext)
144 {
145 const PropertyType* CastedProperty = CastProperty<PropertyType>(Property);
146 if (CastedProperty != nullptr && CastedProperty->GetFName() == VariableName)
147 {
148 const VariableType OldValue = CastedProperty->GetPropertyValue_InContainer(Object, 0);
149 CastedProperty->SetPropertyValue_InContainer(Object, OldValue + Value);
150 return;
151 }
152 }
153
154 UE_LOG(
155 LogDlgSystemReflectionHelper,
156 Warning,
157 TEXT("Failed to modify %s %s from %s - property not found!"),
158 *PropertyType::StaticClass()->GetName(), *VariableName.ToString(), *Object->GetName()
159 );
160 }
161
162
163 // Attempts to set the property VariableName from Object
164 template <typename PropertyType, typename VariableType>
165 static void SetVariable(UObject* Object, FName VariableName, const VariableType NewValue)
166 {
167 if (!IsValid(Object))
168 {
169 UE_LOG(
170 LogDlgSystemReflectionHelper,
171 Error,
172 TEXT("Failed to set %s %s of Object that is null (not valid)"),
173 *PropertyType::StaticClass()->GetName(), *VariableName.ToString()
174 );
175 return;
176 }
177
178 for (auto* Property = Object->GetClass()->PropertyLink; Property != nullptr; Property = Property->PropertyLinkNext)
179 {
180 const PropertyType* CastedProperty = CastProperty<PropertyType>(Property);
181 if (CastedProperty != nullptr && CastedProperty->GetFName() == VariableName)
182 {
183 CastedProperty->SetPropertyValue_InContainer(Object, NewValue);
184 return;
185 }
186 }
187
188 UE_LOG(
189 LogDlgSystemReflectionHelper,
190 Warning,
191 TEXT("Failed to set %s %s from %s - property not found!"),
192 *PropertyType::StaticClass()->GetName(), *VariableName.ToString(), *Object->GetName()
193 );
194 }
195
196 // Gathers the name of all variables in ParticipantClass (except those properties that belong to the black listed classes) from the type defined by PropertyClass
197 // If the BlacklistedClasses is empty it will get the default ones from the settings
198 template <typename ContainerType>
199 static void GetVariableNames(
200 const UClass* ParticipantClass,
201 const FNYPropertyClass* PropertyClass,
202 ContainerType& OutContainer,
203 const TArray<UClass*>& BlacklistedClasses
204 )
205 {
206 if (!IsValid(ParticipantClass) || !PropertyClass)
207 {
208 return;
209 }
210
211 auto IsPropertyAtStartOfBlacklistedClass = [&BlacklistedClasses](FNYProperty* CheckProperty) -> bool
212 {
213 for (UClass* Class : BlacklistedClasses)
214 {
215 if (!IsValid(Class))
216 {
217 continue;
218 }
219
220 // CheckProperty is at the start of the blacklisted class
221 if (Class->PropertyLink == CheckProperty)
222 {
223 return true;
224 }
225 }
226
227 return false;
228 };
229
230 // Property link goes from the left to right where on the left there are the most inner child properties and at the right ther are the top most parents.
231 auto* Property = ParticipantClass->PropertyLink;
232 while (Property != nullptr && !IsPropertyAtStartOfBlacklistedClass(Property))
233 {
234 if (Property->GetClass() == PropertyClass)
235 {
236 OutContainer.Add(Property->GetFName());
237 }
238 Property = Property->PropertyLinkNext;
239 }
240 }
241};
242#endif // NY_REFLECTION_HELPER
DEFINE_LOG_CATEGORY_STATIC(LogApexAPI, Log, All)
UClass FNYPropertyClass
UProperty FNYProperty
UArrayProperty FNYArrayProperty
static To * SmartCastProperty(From *Src)
static void GetVariableNames(const UClass *ParticipantClass, const FNYPropertyClass *PropertyClass, ContainerType &OutContainer, const TArray< UClass * > &BlacklistedClasses)
static void ModifyVariable(UObject *Object, FName VariableName, const VariableType Value, bool bDelta)
static FORCEINLINE To * CastProperty(From *Src)
static FORCEINLINE UField * GetStructChildren(const UStruct *Struct)
static void SetVariable(UObject *Object, FName VariableName, const VariableType NewValue)
static VariableType GetVariable(const UObject *Object, FName VariableName)
static FORCEINLINE const To * CastProperty(const From *Src)