反射在其它的比如说C#,JAVA语言中比较常见。反射概况的来说是描述类在运行时的状态,反射中包含的信息有类名,类数据成员,数据成员类型,还有每个成员位于对象内存映像的偏移(offset),类所有成员函数的信息。
C++本身是不支持反射的,4在C++的基础上搭建了自己的一套反射机制。
UE4的反射机制原理
Property system的层级1
2
3
4
5
6
7
8
9
10
11UField
UStruct
UClass (C++ class)
UScriptStruct (C++ struct)
UFunction (C++ function)
UEnum (C++ enumeration)
UProperty (C++ member variable or function parameter)
(Many subclasses for different types)
上面的文章虽然是很久之前文章,但是还是很厉害。
利用反射对属性进行读写
最近在搞使用ImGui对ini文件进行读写的功能,同时又希望像UE4的Editor那样,对于添加的UCLASS的类中的UPROPERTY属性自动的显示各种类型的UI。于是就研究了一下反射,虽然原理什么的我还是不是很清楚,希望能多读读上面的文章而不是只是单纯的记录下来,终归动还是能动的。
直接贴上代码:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46// Debug settings UI
bool show_about_app = true;
ImGui::Begin("DebugSettings", &show_about_app, ImGuiWindowFlags_AlwaysAutoResize);
// Creaete DebugUI for UObject
bool AnyPropertiesEdited = false;
UClass* obj = DebugSettings->GetClass();
for(TFieldIterator<FProperty> PropertyIterator(obj); PropertyIterator; ++PropertyIterator)
{
FProperty* Property = *PropertyIterator;
if(FBoolProperty* BoolProperty = CastField<FBoolProperty>(Property))
{
// UE_LOG(LogTemp, Log, TEXT("cast bool property successed."));
static bool sampleBool = BoolProperty->GetPropertyValue_InContainer(DebugSettings);
ImGui::Checkbox(TCHAR_TO_ANSI(*BoolProperty->GetName()), &sampleBool);
if(ImGui::IsItemEdited())
{
// Apply changes
BoolProperty->SetPropertyValue(BoolProperty->ContainerPtrToValuePtr<bool>(DebugSettings), sampleBool);
AnyPropertiesEdited = true;
}
}
else if(FIntProperty* IntProperty = CastField<FIntProperty>(Property))
{
// UE_LOG(LogTemp, Log, TEXT("cast int property successed."));
static int sampleInt = IntProperty->GetPropertyValue_InContainer(DebugSettings);
ImGui::InputInt(TCHAR_TO_ANSI(*IntProperty->GetName()), &sampleInt);
if(ImGui::IsItemEdited())
{
// Apply changes
IntProperty->SetPropertyValue(IntProperty->ContainerPtrToValuePtr<int>(DebugSettings), sampleInt);
AnyPropertiesEdited = true;
}
}
else if(auto StrProperty = CastField<FStrProperty>(Property))
{
FString sampleStr = StrProperty->GetPropertyValue_InContainer(DebugSettings);
// TODO:
}
}
if(AnyPropertiesEdited)
{
DebugSettings->SaveConfig();
}
ImGui::End();
没有对应所有的类型,但是知道了方法就行了。
这其中有一篇文章很重要:
UE4.25版本更改了UProperty->FProperty
,跟之前写法会有些出入
还参考了其他人的提问的文章
利用反射对函数进行操作
有一天突发奇想,UE4的反射机制可不可以遍历UObject
中的UFUNCTION
?然后根据UUFUNCTION
的的类型,比如说根据Meta修饰符来切换ImmGui的UI类型,Button啥的。
遍历UFUNCTION
貌似是可行的:
1 | void UMyClass::ListAllObjectUFunctions(const UObject* Object) { |
至于自定义的Meta修饰符,我还没开始调查。啧。
参考资料
感觉上面的文章都很重要。尤其是最后一篇。