news 2026/9/13 12:05:48

GDevelop 扩展如何用 PropertyDescriptor 声明对象属性并实现 updateProperty

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
GDevelop 扩展如何用 PropertyDescriptor 声明对象属性并实现 updateProperty

GDevelop 扩展如何用 PropertyDescriptor 声明对象属性并实现 updateProperty

【免费下载链接】GDevelop🎮 Open-source, cross-platform 2D/3D/multiplayer game engine designed for everyone.项目地址: https://gitcode.com/GitHub_Trending/gd/GDevelop

开发 GDevelop 扩展时,如果你的对象(object)或行为(behavior)有用户需要在编辑器里修改的字段——文本、数字、开关、资源引用——就需要做两件事:用PropertyDescriptor声明这些属性,让属性面板自动生成对应的输入控件;再实现updateProperty,在用户在编辑器中修改属性时把新值写回对象内容。GDevelop 的官方说明文档 Properties-schema-and-PropertiesEditor-explanations.md 描述了这套机制,本文结合仓库中 Video 对象和 TextObject 的真实代码,给出 JS 扩展的完整操作路径。

属性从哪里来:PropertyDescriptor 与属性面板的关系

在 GDevelop 中,一个"属性"由 GDCore 里的 PropertyDescriptor 类定义。属性面板的显示逻辑是:

  1. 对象/行为声明一组PropertyDescriptor(每个含值、类型、标签等);
  2. 这些描述符被映射为 PropertiesEditor 使用的 schema;
  3. 用户改动属性后,编辑器回调你实现的updateProperty(C++ 中为UpdateProperty)。

文档明确提示:只声明属性是不够的,还必须实现updateProperty,它会在用户在编辑器中修改属性时被调用,你可以在其中加入任何需要的校验逻辑。

PropertyDescriptor的完整 API 见 Core/GDCore/Project/PropertyDescriptor.h,除SetValueSetTypeSetLabel外还支持SetDescriptionSetGroupAddChoiceSetHiddenSetDeprecatedSetAdvanced等链式调用,返回PropertyDescriptor&,因此可以连续调用。

在 JS 扩展中声明属性(getProperties)

以仓库中 Video 扩展的 Extensions/Video/JsExtension.js 为例,在ObjectJsImplementation上挂一个getProperties函数,返回gd.MapStringPropertyDescriptor

videoObject.getProperties = function () { var objectProperties = new gd.MapStringPropertyDescriptor(); objectProperties .getOrCreate('Looped') .setValue(this.content.loop ? 'true' : 'false') .setType('boolean') .setLabel(_('Loop the video')) .setGroup(_('Playback settings')); objectProperties .getOrCreate('Volume') .setValue(this.content.volume.toString()) .setType('number') .setLabel(_('Video volume (0-100)')) .setGroup(_('Playback settings')); objectProperties .getOrCreate('videoResource') .setValue(this.content.videoResource) .setType('resource') .addExtraInfo('video') .setLabel(_('Video resource')); return objectProperties; };

对应的默认值放在videoObject.content中(如opacity: 255, loop: false, volume: 100),getProperties只负责把content里的值转成描述符。getOrCreate的参数就是属性名,后续updateProperty收到的propertyName与它一致。

文档中列出的可用setType取值:

类型编辑器控件附加要求
"string"文本输入框默认类型
"number"数字输入框
"boolean"复选框
"resource"资源选择器必须再调用addExtraInfo指定资源类型:"image""audio""font""json"

资源类型下,值以字符串形式存储,但编辑器会显示选择器,被选中的资源会加入项目。

注意:类型字符串的合法取值由"负责更新属性网格的类"来解释(见PropertyDescriptor.h中对SetType的注释),上表来自官方说明文档;如果你使用文档未列出的自定义类型,需要自行确认属性面板一侧是否认识它。

实现 updateProperty 把编辑器输入写回 content

同一个文件中,updateProperty接收属性名和新值,按名字分发更新this.content,处理成功返回true,不认识的名字返回false

videoObject.updateProperty = function (propertyName, newValue) { if (propertyName === 'Opacity') { this.content.opacity = parseFloat(newValue); return true; } if (propertyName === 'Looped') { this.content.loop = newValue === '1'; return true; } if (propertyName === 'Volume') { this.content.volume = parseFloat(newValue); return true; } if (propertyName === 'videoResource') { this.content.videoResource = newValue; return true; } return false; };

要点:

  • 新值newValue始终是字符串,数字属性用parseFloat转换,布尔属性按编辑器传入的字符串形式判断(Video 示例中对Looped判断newValue === '1')。
  • 文档建议在这个方法里加入属性校验逻辑,这是编辑器侧值生效前的必经回调。
  • 除对象属性外,Video 示例还展示了实例(instance)侧的一对方法:updateInitialInstancePropertygetInitialInstanceProperties,签名分别为(instance, propertyName, newValue)(instance),用于场景内实例的可编辑属性;实例不需要额外属性时返回false/ 空的MapStringPropertyDescriptor即可。

C++ 扩展的对应写法

C++ 侧的用法与 JS 基本一致:对象实现GetProperties()返回std::map<gd::String, gd::PropertyDescriptor>,并实现UpdateProperty。官方说明文档给出的 Video 对象示例(文档示例,照抄自上述文档):

std::map<gd::String, gd::PropertyDescriptor> videoObject::GetProperties() const { std::map<gd::String, gd::PropertyDescriptor> properties; properties[_("Opacity")] .SetValue(opacity) .SetType("number") .setLabel(_("Video opacity (0-255)")); // ... 其余属性同理 properties[_("Video resource")] .SetValue(videoDataFilename) .SetType("resource") .AddExtraInfo("video") .SetLabel(_('Video resource')); return properties; }

仓库中可直接参考的完整 C++ 实现是 TextObject:TextObject::UpdateProperty位于第 44 行,TextObject::GetProperties位于第 139 行,行为(behavior)与实例属性也有各自的对应方法。

修改后如何验证属性生效

按 Extensions/Video/JsExtension.js 文件头的说明:

  • JsExtension.js会被监视,编辑器正在运行时改动会被自动导入;
  • 也可以手动执行导入:在newIDE/app/scripts目录下运行node import-GDJS-Runtime.js
  • 如果改动后扩展没有加载,打开开发者控制台搜索错误信息,这是文档给出的排查入口。

加载成功后,在编辑器中创建你的对象,属性面板会按getProperties的声明自动生成输入框(类型决定控件样式),修改某个属性触发updateProperty;返回false的名字不会被处理。

限制与后续方向

  • typeextraInformation本身是"任意字符串",其合法取值由解释它们的类决定(PropertyDescriptor.h注释原文),新增类型前先核对属性面板一侧的支持范围。
  • 官方文档指出PropertyDescriptor与前端 schema 两个概念"应当在未来合并"(原文:The two concepts should be merged at some point),即这条链路两侧的实现仍在演进,改动前建议对照当前版本的 PropertiesMapToSchema.js。
  • 属性声明(getProperties/GetProperties)与回调(updateProperty/UpdateProperty)缺一不可,只声明属性时用户看到的控件不会把值写回对象。

【免费下载链接】GDevelop🎮 Open-source, cross-platform 2D/3D/multiplayer game engine designed for everyone.项目地址: https://gitcode.com/GitHub_Trending/gd/GDevelop

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/13 12:05:25

STM32嵌入式开发入门:从点灯到物理层调试的实操指南

1. 别再被“嵌入式”三个字吓退&#xff1a;这其实是一门可触摸、可调试、可点亮LED的实操手艺你是不是也经历过这样的场景&#xff1a;打开招聘网站&#xff0c;嵌入式开发岗写着“精通C语言、熟悉STM32、掌握RTOS、了解硬件原理”&#xff0c;再点开学习路线图&#xff0c;密…

作者头像 李华
网站建设 2026/9/13 12:04:04

Java中static关键字的深度解析与应用实践

1. static关键字的本质解析 static关键字在面向对象编程中扮演着独特角色&#xff0c;它打破了常规成员变量与方法的绑定规则。与实例成员不同&#xff0c;static成员属于类本身而非特定对象。这种设计带来了内存分配和行为模式的根本差异&#xff1a; 类加载时初始化 &#…

作者头像 李华
网站建设 2026/9/13 12:04:04

氛围炒股:市场情绪驱动的短线交易策略解析

1. 氛围炒股的概念解析"氛围炒股"是近年来在投资圈兴起的一种新型投资策略&#xff0c;它不同于传统基于基本面分析或技术分析的投资方法&#xff0c;而是更注重市场情绪和群体心理对股价的影响。简单来说&#xff0c;就是通过捕捉市场参与者的集体情绪波动来寻找交易…

作者头像 李华
网站建设 2026/9/13 12:03:45

如何为 C 扩展模块用 mypy 的 stubgen --inspect-mode 生成类型存根?

如何为 C 扩展模块用 mypy 的 stubgen --inspect-mode 生成类型存根&#xff1f; 【免费下载链接】mypy Optional static typing for Python 项目地址: https://gitcode.com/GitHub_Trending/my/mypy 当你的 Python 项目引用了一个没有类型信息的 C 扩展模块时&#xff…

作者头像 李华
网站建设 2026/9/13 12:01:57

单节锂电池升压至48V的拓扑选择与FP7209恒流设计要点

1. 为什么单节电池要升压到48V&#xff1f;——从供电瓶颈看拓扑选择的底层逻辑你手头有一块标称3.7V的锂电&#xff0c;想驱动一个需要48V输入的LED模组或小型电机控制器。直接接上去&#xff1f;灯不亮、电机不动&#xff0c;连IC都可能报欠压锁死。这不是电压不够的问题&…

作者头像 李华