[自研引擎]GAMES104 反射系统

目录

前言

一、代码框架说明

1.反射宏:

2.反射标签

3.反射功能类

4.反射生成面板过程

二、使用反射系统实现功能

1.新增Struct

2.新添加一个成员

3.面板显示

4.跳跃逻辑修改

三、结果展示

前言

掌握Piccolo中反射宏和反射标签的用法,选择自己感兴趣的系统,给它管理的Component结构增加或修改一个属性,检查它及ComPonent结构的反射宏和反射标签,确保它能够被正确的反射。

一、代码框架说明

1.反射宏:

CLASS(class_name, tags···)

用以反射类型的声明,class_name参数填写类型名称,如果需要继承基类则直接按继承写法写在该参数内,tags参数填写传递给反射系统的反射标签,多个标签需要以','分隔

例:

STRUCT(struct_name, tags···)

用以反射结构体的声明,struct_name参数填写结构体名称,tags参数填写传递给反射系统的反射标签,多个标签需要以','分隔;

例:

META(tags···)

用以给类或结构体的属性增加反射信息标签,写在属性定义前,tags参数填写传递给反射系统的反射标签,多个标签需要以','分隔;

例:

REFLECTION_TYPE(class_name) 

用以提供反射访问器的声明,配合CLASS使用,写在类型定义前,class_name填写类型名称

例:

REFLECTION_BODY(class_name)

对访问器进行友元声明,允许访问器访问其私有属性,写在类型定义内第一行,class_name填写类型名称,需配合REFLECTION_TYPE;、

例:

2.反射标签

Fields

表明类型或结构体中除特殊标记的属性外(如Disable),其余所有属性均需要反射,该标签需要在CLASS或STRUCT中声明。如下图中,PhysicsControllerConfig类型标记了Fields标签,因此其所有属性都支持反射

WhiteListFields

表明类型或结构体中只有标记过的属性才允许反射(即被设置为Enable标签),该标签需在CLASS或STRUCT中声明。如下图中,Motorcomponent类型标记了WhiteListField标签,因此只有被设定为Enable的才允许反射;

Disable

表明该属性无需反射,该标签需要在属性前以META参数的形式声明,且只有在CLASS或STRUCT中声明为Fields时有效。

Enable

表明该属性需要反射,该标签需要在属性前以META参数的形式声明,且只有在CLASS或STRUCT中声明为WhiteListFields时有效

3.反射功能类

4.反射生成面板过程

Piccolo中Components Details面板通过反射系统自动生成,显示场景中选中物体的所有component信息,如下图所示:

实现思路:

使用反射系统,将复杂类型拆解为UI控件可直接表示的原子类型,生成对应的UI控件,形成原子类型控件树,展示复杂类型信息

实现过程:

1.在editor_ui.cpp文件的showEditorDetailWindow方法中,获取选中物体的所有component对象

2.为每个component对象构造反射实例,并依次调用createComponentUI对反射实例进行类型拆解

3.在editor_ui.cpp文件的createComponentUI方法中,先获取该类型的所有基类反射实例,并递归调用该方法生成基类的UI,然后通过调用createLeafNodeUI方法生成该类型属性UI

4.在editor_ui.cpp文件的createLeafNodeUI方法中,获取到所有属性访问器

5.遍历所有属性访问器,使用属性类型名称查找对应的构建方法,传入属性名称和属性地址,进行最后的UI生成

6.UI生成过程中,需要对UI支持的原子类型进行数据和UI控件的绑定,因此需要建立原子类型的UI构建方法表,m_editor_ui_creator是一个map<std::string, std::function<const std::string&, void*>>,对于每一种UI支持的原子类类型,都需要注册其属性名及处理方法

7.除了原子类型外,对于复杂类型,需要继续调用createClassUI方法进行拆解

8.对于容器类型,如array,需要遍历array,对于每个元素进行;类型判断,原子类型则直接生成UI,非原子类型继续调用createClassUI进行类型拆解

二、使用反射系统实现功能

1.新增Struct

在motor_component.h中新增一个结构体MyStruct

value:表示实际值

min_value:表示最小值

max_value:表示最大值

2.新添加一个成员

在motorComponent中新加一个成员,表示自己的跳跃高度,默认值为1.0f,最小跳跃高度是0.5f,最大跳跃高度是10.0f

3.面板显示

在editor_ui.cpp中加入如下代码

//用于在编辑器界面创建一个用于编辑自定义结构体的UI元素
        //将lambda函数绑定到m_editor_ui_creator
        //该函数接受一个名称参数name和一个指向MyStruct对象的指针参数 并返回一个void类型
        m_editor_ui_creator["MyStruct"] = [this](const std::string& name, void* value_ptr) -> void{
            //检查当前节点的深度是否为-1,如果不是-1 表示当前正在渲染一个节点 可以继续创建UI元素
            if(g_node_depth != -1)
            {
                //根据传入名称 创建一个用于标签的字符串
                std::string label = "##" + name;
                //使用ImGui库创建一个文本标签,显示传入的名称
                ImGui::Text("%s", name.c_str());
                //将下一个UI元素放在同一行
                ImGui::SameLine();
                //使用ImGui库创建一个滑动条UI元素,用于编辑MyStruct对象的value属性
                //滑动条的标签为之前创建的label字符串,滑动条的范围由MyStruct对象的min_value
                //和max_value属性决定
                ImGui::SliderFloat(label.c_str(),
                &static_cast<MyStruct*>(value_ptr)->value,
                static_cast<MyStruct*>(value_ptr)->min_value,
                static_cast<MyStruct*>(value_ptr)->max_value);
            }
        };

4.跳跃逻辑修改

将跳跃高度设置为MyStruct中value的高度,从而实现跳跃高度的修改

在motor_component.cpp中做如下修改:

三、结果展示

修改跳跃高度为区间[0.5, 10]

  • 22
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值