引擎版本 4.22.0

属性类型定制简介

在介绍属性类型定制前先了解下引擎提供的默认的详细布局。

  • 默认详细布局

只要我们的UPROEPRTY类型是值类型,编辑器系统就会在详细面板为你创建一个默认布局。如下图所示:

  • 属性类型定制(Property Type Customization)

当你创建了需要更改布局的自定义结构时,属性类型定制就变得非常有用。目前属性类型定制只适用于USTRUCT的接口,IPropertyTypeCustomization实现的所有功能都只与结构体一起工作。

属性类型定制最常见的用法时创建比默认显示更好的布局,或者创建设置数据的更直观的小部件。比如引擎默认提供的通过颜色拾取器来设置颜色,软对象选择设置等。

快速创建属性类型定制

  • 创建需要定制化显示的结构体

为保证在定制化代码中可以轻松访问该结构体中相关属性,该结构使用USTRUCT宏标记,成员变量使用UPROPERTY宏标记。

这里先记录下未定制化时在详细面板中的效果:

  • 创建属性类型定制化类

类名请确保与自定义结构体匹配,并在末尾加上“Customization”。

该类需要继承自IPropertyTypeCustomization接口并实现接口的方法。

我们注意到IPropertyTypeCustomization接口中主要包括两个方法:CustomizeHeader和CustomizeChildren。我们不妨看看源码中的注释:

可以看出CustomizeHeader主要用来处理属性的头,而属性头是该属性在详细面板中显示的所在的行,且不能额外添加行;而CustomizeChildren主要用来处理属性中需要定制化显示的子属性及添加额外的行。一般情况下对于需要定制化显示的结构体属性中只有一个属性时可以放在CustomizeHeader中处理,而一旦该结构体中的属性有多个需要定制化显示则最好放到CustomChildren中处理。

  • 注册属性类型定制化

仅仅创建属性类型定制化时不够的。为了让编辑器知道它的存在,你必须在正确的模块中注册它。由于属性类型定制化属于编辑器环境下使用的,最好将其注册在你游戏的编辑器模块。假如你的游戏中只有一个游戏主模块,你又不想添加一个专门的编辑器模块,那么你可以将其注册在游戏主模块中,但需要使用WITH_EDITOR宏标记。

这里给出一个示例,示例中将属性类型定制化类注册到专门的编辑器模块启动函数中:

当然同样需要在专门的编辑器模块的Build.cs中私有依赖PropertyEditor模块:

属性类型定制相关实验

前边介绍了创建属性类型定制的简单步骤,其中IPropertyTypeCustomization中两个方法可能还有点不太明白。这里将在前边的基础上结合一些实验来介绍定制化显示的一些操作。

  • CustomizeChildren和CustomizeHeader函数中均不填写任何代码

可以看到在定义的结构体蓝图中是无法看到MyTestStruct相关属性的,很显然需要补充代码啦。

  • 仅在CustomizeHeader中填写代码

在该方法中主要需要处理的是设置HeaderRow中的内容(该属性在详细面板中显示的内容),HeaderRow包含两部分:NameContent和ValueContent。如下图所示的默认bool在详细面板中分割线左侧中显示的属性名字(红框内)是在NameContent中来处理的,分割线右侧属性的值(蓝框内)是中ValueContent来处理的:

假设我们只处理NameContent部分,代码及效果下图所示:

可见只显示属性名TestStruct,特别地如果想要改名显示的属性名则使用如下代码:

由于我们的结构体包含两个变量,如果全部放到CustomizeHeader函数中处理的话则只能在ValueContent中显示了。

这里通过GetChildHandle方法分别得到结构体中两个变量Name和Table,接着使用默认的SProperty来绘制,效果如下图所示:

如果我们想要隐藏变量Table和Name的名字则只需要将代码中注释掉的.ShouldDisplayName(false)开启:

这里是为了省事直接通过SProperty来绘制,所以显示的效果很一般是默认属性显示。如果需要自己个性化处理则同样需要写Slate代码来处理,不过需要在一些事件中设置属性值或者获取属性值等,常用的方法是PropertyHandle中的SetValue和GetValue,这里就不再介绍,可以自行查看后边推荐的一些源码。

  • 仅在CustomizeChildren中填写代码

常用的方法是StructBuilder.AddCustomRow,也就是添加一个自定义内容作为结构体的孩子。

效果如下:

可以看到跟前边仅在CustomizeHeader中显示效果一致。但CustomizeHeader中只能添加一行,这里可以添加多行。比如接下来将结构体中变量Name和Table分两行显示:

效果如下图所示:

  • CustomizeHeader和CustomizeChildren均填写代码

保持前边CutomizeChildren最后的代码不变,在CustomizeHeader中添加如下代码:

效果如下图所示:

此时可以看到跟不做定制化处理的默认显示效果差不多。

由此也可看出CustomizeHeader和CustomizeChildren均填写代码的情况下将产生折叠效果,即CustomizeHeader中充当结构体名字显示的任务,CustomizeChildren中显示结构体成员显示的任务。至于选择在哪个函数中填写逻辑根据个人喜好即可,不必太过纠结。

  • 区分是否在结构体定义蓝图中

前边的实验无一例外都是在结构体定义蓝图中的详细面板中显示,但我们还可以将自定义结构体应用到蓝图变量定义中或者DataTable中,如下图所示:

此时如果想在结构体定义蓝图中和其他环境中做不同的显示效果就需要做进一步的区分。

目前暂时没有好的办法,有一个不太靠谱的方法,代码如下:

那么对于在结构体定义蓝图中可以判断该值是否是Default Values;作为蓝图变量则判断是否是Default Value;DataTable中则判断是否是RowValue。大家如果有更好的区分方法请告知哈。

巧用属性类型定制

前边介绍了属性类型及其使用方法,也许有人会说感觉没有太大用途,无非是在详细面板中对一个结构体进行定制化显示而已。笔者近期需要做一个DataTable中引用表的一个功能,深深体会到属性类型定制的妙用。

不妨介绍下相关需求:

我们一般做DataTable需要定义一个表结构,针对手游项目的话考虑到热更新,表结构一般使用蓝图来定义。假设我有一张奖励表中需要有一个字段类型是int,填写的是物品表中的物品ID(行名)。那么我就希望在定义奖励表结构时可以制定要引用哪张表如物品表,在对奖励表中物品ID字段编辑时希望通过一个下拉菜单来显示物品表中所有的物品ID,这样不仅方便还保证不会填错物品ID。

此时要实现此功能就只需要定义一个自定义结构体包含两个成员变量int32 ID和TSoftObjectPtr<UDataTable> Table。在奖励表结构蓝图定义中添加字段时选择自定义结构体,同时在该蓝图中仅显示选择表的变量Table,而在奖励表的DataTable中仅显示一个下拉菜单来设置自定义结构体中变量ID的值。

不妨看下效果图:

注意这里为了同时显示物品表ID对应的名字,就在结构体中额外添加了一个引用的表中说明性值的列名。

可参考的相关源码

我们对于属性类型定制实际操作时可能需要一些参考源代码,这里给出相关代码大家可以自行参阅。

Engine/Source/Editor/DetailCustomizations该模块中全部时详细定制相关,其中不仅包含了属性类型定制也包含类定制,我们如果需要类定制也可参考其中的代码。

特别地值得一看的是DataTableCustomization.cpp,SoftObjectPathCustomization.cpp

用户自定义属性表结构设计_属性类型定制及其妙用相关推荐

  1. 全库模式 用户模式 表模式_暗模式,亮模式和用户的故事

    全库模式 用户模式 表模式 I have been working on designing a UI for an app that has individuals over the age of ...

  2. mysql 用户签到表设计_用户签到表的设计思路与数据库实现

    签到做为,一个促进用户粘性的手段已经很成熟了. 这里说下,个人的一些设计表思路 添加用户配置表.主键关联User表,即可. CREATE TABLE `cft_user_signin` ( `id` ...

  3. 用户关系表 存储_列式存储系列(一)CStore

    作者:辛庸,阿里巴巴计算平台事业部 EMR 技术专家.Apache Hadoop,Apache Spark commiter.对 Hadoop.Spark.Hive.Druid 等大数据组件有深入研究 ...

  4. UI组件库Form表单_数字类型验证之坑实现数字框

    目录 Input 输入框 实现数字框封装使用 项目需求 : 使用的饿了么组件库的 input 框 , 但是想要 实现用户只能输入 数字 的功能 , So 看到了数字类型的验证 (缺点 :不能阻止用户输 ...

  5. mysql表结构设计_数据库表结构设计

    1. 原始单据与实体之间的关系 可以是一对一.一对多.多对多的关系.在一般情况下,它们是一对一的关系:即一张原始单据对 应且只对应一个实体.在特殊情况下,它们可能是一对多或多对一的关系,即一张原始单证 ...

  6. 订单中心表结构设计_卧式加工中心立柱的分析设计

    简介 浙江工业大学先进加工技术重点实验室 等  作者:项秉乐 常新山 秦宝荣 张冬冬 0 引言 曲轴是发动机的核心部件之一,其加工精度要求较高,传统的卧式车削和立式铣削已经无法满足曲轴越来越高的精度要 ...

  7. mysql表结构设计_表结构设计

    持续更新... 用户表 create table NHSD_User(Id nvarchar(25) default(newid()) primary key not null,Phone int,- ...

  8. 用户关系表 存储_如何解决oracle 19c中创建用户报错的故障

    背景:Oracle 19c 创建表用户的时候,采用11g的语句会报一下错误. ORA-01918: user 'BISTU_ODS' does not exist 原因:oracle从12c开始增加了 ...

  9. 订单中心表结构设计_商超仓储中心物流拣选系统的设计与应用

    文|深圳市今天国际物流技术股份有限公司 何敏.田晓美 商超仓储中心品规种类多,日销量大,出库频率高,分拣流程复杂.作为商超仓储中心重要的工艺流程,物流分拣的设计至关重要.本文总结了常见的物流拣选作业模 ...

最新文章

  1. 开源项目:windows下使用MinGW+msys编译ffmpeg
  2. R语言ggplot2可视化:使用scale_shape_identity函数显示pch点形状、使用geom_text函数为pch形状添加标(plot characters)
  3. SAP Query达到select * where 的效果 2011-04-29
  4. python二维数组初始化
  5. stm32捕获占空比_基于STM32超声波避障小车
  6. 万用表怎么测量电池容量_如何使用万用表,使用万用表测量常用的六个方面
  7. 剑指offer刷题(java)|二维数组中的查找|替换空格|leetcode刷题
  8. 开发工具:Git和SVN有哪些差异,看完你就懂了?
  9. 最大子矩阵(普通和01)
  10. matlab梯形模糊数,基于梯形模糊数的OWA方法与matlab应用
  11. python调用java方法_python调用Java方法传入HashMap ArrayList
  12. Xml序列化自引用/循环引用问题2
  13. barco控制软件支持linux_vnc远程控制软件linux,在linux系统上能够使用的vnc远程控制软件...
  14. 环境部署(二):Linux下安装jenkins
  15. 如何用TensorFlow生成令人惊艳的分形图案
  16. 【参考文献】平滑肌细胞生长培养
  17. property_get和property_set使用方法
  18. 【渝粤题库】广东开放大学 企业财务报表分析 形成性考核
  19. 安卓Push Rejected解决
  20. 还在用 Guava Cache?它才是 Java 本地缓存之王!

热门文章

  1. 阅读后这篇文章后,python正则表达式完全弄懂了
  2. 源码分析参考:Scheduler
  3. 如何基于 Flink 生成在线机器学习的样本?
  4. sobel prewitt算法 模板加权模糊的解释 + 两类边缘下的二阶导数值
  5. 【opencv学习】【图像的数值计算操作】
  6. 每天进步一点点《ML - 支持向量机》
  7. [机器学习-sklearn]K-means之make_blobs聚类数据生成器
  8. 吴恩达深度学习 —— 3.2 神经网络表示
  9. CSDN-Markdown--基本语法功能效果
  10. java blob字段_java 存取blob字段