Last active
October 20, 2025 13:23
-
-
Save badforlabor/a01474ead3dcd8ebc09297a1059b4af3 to your computer and use it in GitHub Desktop.
UnrealEngine. Set values using Property System (Reflection)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // 反射工具 | |
| class FReflectionHelper | |
| { | |
| public: | |
| template <typename T> | |
| static T GetDefault() | |
| { | |
| static T t; | |
| return t; | |
| } | |
| static bool HasAttr(UObject* Ptr, const char* AttrName) | |
| { | |
| if (!Ptr) | |
| { | |
| return false; | |
| } | |
| return Ptr->GetClass()->FindPropertyByName(AttrName) != nullptr; | |
| } | |
| static int GetValue(UObject* Ptr, const char* AttrName) | |
| { | |
| if (Ptr) | |
| { | |
| FIntProperty* IntProp = Cast<FIntProperty>(Ptr->GetClass()->FindPropertyByName(AttrName)); | |
| if (IntProp) | |
| { | |
| void* PropertyAddress = IntProp->ContainerPtrToValuePtr<void>(Ptr); | |
| return IntProp->GetPropertyValue(PropertyAddress); | |
| } | |
| } | |
| return 0; | |
| } | |
| static void SetValue(UObject* Ptr, const char* AttrName, int Value) | |
| { | |
| if (Ptr) | |
| { | |
| FIntProperty* IntProp = Cast<FIntProperty>(Ptr->GetClass()->FindPropertyByName(AttrName)); | |
| if (IntProp) | |
| { | |
| void* PropertyAddress = IntProp->ContainerPtrToValuePtr<void>( | |
| Ptr); | |
| IntProp->SetPropertyValue(PropertyAddress, Value); | |
| } | |
| } | |
| } | |
| template <typename T> | |
| static bool HasAttr(UObject* Ptr, const char* AttrName) | |
| { | |
| if (!Ptr) | |
| { | |
| return false; | |
| } | |
| return Cast<T>(Ptr->GetClass()->FindPropertyByName(AttrName)) != nullptr; | |
| } | |
| // 如 int, FIntProperty | |
| template <typename PropType> | |
| static typename PropType::TCppType TGetValue(UObject* Ptr, const char* AttrName) | |
| { | |
| if (Ptr) | |
| { | |
| PropType* IntProp = Cast<PropType>(Ptr->GetClass()->FindPropertyByName(AttrName)); | |
| if (IntProp) | |
| { | |
| void* PropertyAddress = IntProp->ContainerPtrToValuePtr<void>(Ptr); | |
| return IntProp->GetPropertyValue(PropertyAddress); | |
| } | |
| } | |
| // static typename PropType::TCppType Ret; | |
| return GetDefault<typename PropType::TCppType>(); | |
| } | |
| // 如 int, FIntProperty | |
| template <typename PropType> | |
| static void TSetValue(UObject* Ptr, const char* AttrName, const typename PropType::TCppType& Value) | |
| { | |
| if (Ptr) | |
| { | |
| PropType* IntProp = Cast<PropType>(Ptr->GetClass()->FindPropertyByName(AttrName)); | |
| if (IntProp) | |
| { | |
| void* PropertyAddress = IntProp->ContainerPtrToValuePtr<void>(Ptr); | |
| IntProp->SetPropertyValue(PropertyAddress, Value); | |
| } | |
| } | |
| } | |
| // 如 int, FIntProperty | |
| template <typename PropType> | |
| static TArray<typename PropType::TCppType> TGetArrValue(UObject* Ptr, const char* AttrName) | |
| { | |
| TArray<typename PropType::TCppType> Ret; | |
| if (Ptr) | |
| { | |
| FArrayProperty* ArrayProperty = Cast<FArrayProperty>(Ptr->GetClass()->FindPropertyByName(AttrName)); | |
| if (ArrayProperty) | |
| { | |
| PropType* StrProp = CastField<PropType>(ArrayProperty->Inner); | |
| if (StrProp) | |
| { | |
| void* PropertyAddress = ArrayProperty->ContainerPtrToValuePtr<void>(Ptr); | |
| FScriptArrayHelper ArrayHelper(ArrayProperty, PropertyAddress); | |
| const int32 NumElements = ArrayHelper.Num(); | |
| for (int32 Index = 0; Index < NumElements; Index++) | |
| { | |
| void* ArrayData = ArrayHelper.GetRawPtr(Index); | |
| if (ArrayData) | |
| { | |
| Ret.Add(StrProp->GetPropertyValue(ArrayData)); | |
| } | |
| } | |
| } | |
| } | |
| } | |
| return Ret; | |
| } | |
| // 如 int, FIntProperty | |
| template <typename PropType> | |
| static void TAddArrValue(UObject* Ptr, const char* AttrName, const typename PropType::TCppType& V) | |
| { | |
| if (Ptr) | |
| { | |
| FArrayProperty* ArrayProperty = Cast<FArrayProperty>(Ptr->GetClass()->FindPropertyByName(AttrName)); | |
| if (ArrayProperty) | |
| { | |
| PropType* StrProp = CastField<PropType>(ArrayProperty->Inner); | |
| if (StrProp) | |
| { | |
| void* ArrPropertyAddress = ArrayProperty->ContainerPtrToValuePtr<void>(Ptr); | |
| FScriptArrayHelper ArrayHelper(ArrayProperty, ArrPropertyAddress); | |
| int Idx = -1; | |
| if (StrProp->PropertyFlags & CPF_IsPlainOldData) | |
| { | |
| Idx = ArrayHelper.AddUninitializedValue(); | |
| } | |
| else | |
| { | |
| Idx = ArrayHelper.AddValue(); | |
| } | |
| if (Idx >= 0) | |
| { | |
| void* ArrayData = ArrayHelper.GetRawPtr(Idx); | |
| if (ArrayData) | |
| { | |
| StrProp->SetPropertyValue(ArrayData, V); | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } | |
| // 如 int, FIntProperty | |
| template <typename PropType> | |
| static void TSetArrValue(UObject* Ptr, const char* AttrName, const TArray<typename PropType::TCppType>& V) | |
| { | |
| if (Ptr) | |
| { | |
| FArrayProperty* ArrayProperty = Cast<FArrayProperty>(Ptr->GetClass()->FindPropertyByName(AttrName)); | |
| if (ArrayProperty) | |
| { | |
| PropType* StrProp = CastField<PropType>(ArrayProperty->Inner); | |
| if (StrProp) | |
| { | |
| void* ArrPropertyAddress = ArrayProperty->ContainerPtrToValuePtr<void>(Ptr); | |
| FScriptArrayHelper ArrayHelper(ArrayProperty, ArrPropertyAddress); | |
| if (StrProp->PropertyFlags & CPF_IsPlainOldData) | |
| { | |
| ArrayHelper.EmptyAndAddUninitializedValues(V.Num()); | |
| } | |
| else | |
| { | |
| ArrayHelper.EmptyAndAddValues(V.Num()); | |
| } | |
| for (int i = 0; i < V.Num(); i++) | |
| { | |
| void* ArrayData = ArrayHelper.GetRawPtr(i); | |
| if (ArrayData) | |
| { | |
| StrProp->SetPropertyValue(ArrayData, V[i]); | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } | |
| #if false | |
| template <typename PropType> | |
| struct Helper | |
| { | |
| typedef typename PropType::TCppType ValueType; | |
| static void Set(UObject* Ptr, const char* AttrName, const ValueType& Value) | |
| { | |
| TSetValue<PropType>(Ptr, AttrName, Value); | |
| } | |
| }; | |
| #endif | |
| static void TestAll(UObject* Ptr) | |
| { | |
| { | |
| TAddArrValue<FIntProperty>(Ptr, "arr1", 0); | |
| TAddArrValue<FStrProperty>(Ptr, "arr1", TEXT("123")); | |
| auto Ret = TGetArrValue<FIntProperty>(Ptr, "arr1"); | |
| TSetArrValue<FIntProperty>(Ptr, "arr1", Ret); | |
| } | |
| { | |
| HasAttr(Ptr, "v1"); | |
| TSetValue<FIntProperty>(Ptr, "v1", 0); | |
| auto Ret = TGetValue<FIntProperty>(Ptr, "v1"); | |
| } | |
| { | |
| HasAttr(Ptr, "v2"); | |
| TSetValue<FStrProperty>(Ptr, "v2", "123"); | |
| auto Ret = TGetValue<FStrProperty>(Ptr, "v2"); | |
| } | |
| { | |
| #if false | |
| Helper<FStrProperty>::Set(Ptr, "v2", "123"); | |
| #endif | |
| } | |
| } | |
| }; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment