A lot of elements in GDevelop can have fields which can be edited by the user. For example:
- a behavior has properties that are, for most behaviors, strings, numbers and booleans.
- an object also has properties that are shown in the editor. They are often strings (the text to display in a text object), numbers (the number of particles), booleans (a checkbox to set if a text is displayed in bold or not) and also sometimes can be a resource (for example, the image to be displayed by a tiled sprite object or the font to be used by a text object).
- an instance on a scene also has a bunch of properties: its X and Y coordinates, its angle, etc...
While some object or behaviors can have their own editor, with a custom interface written in React (find them in newIDE/app/src/ObjectEditor/Editors
for objects and in newIDE/app/src/BehaviorsEditor/Editors
for behaviors), the large majority of object/behavior editors can be automatically generated by looking at the properties of the said objects/behaviors, and creating a field for them.
That's why object and behaviors can have "properties". A property is defined by a class in GDCore called PropertyDescriptor.
-
You can use them when declaring an object or behavior in JavaScript (in
JsExtension.js
). For example, in the case of a Video Object:videoObject.getProperties = function (objectContent) { var objectProperties = new gd.MapStringPropertyDescriptor(); objectProperties .getOrCreate('Opacity') .setValue(objectContent.opacity.toString()) .setType('number') .setLabel(_('Video opacity (0-255)')); objectProperties .getOrCreate('Looped') .setValue(objectContent.loop ? 'true' : 'false') .setType('boolean') .setLabel(_('Loop the video')); objectProperties .getOrCreate('Volume') .setValue(objectContent.volume.toString()) .setType('number') .setLabel(_('Video volume (0-100)')); objectProperties .getOrCreate('videoResource') .setValue(objectContent.videoResource) .setType('resource') .addExtraInfo('video') .setLabel(_('Video resource')); return objectProperties; };
-
Their usage is mostly the same in C++. For example, in the case of a Video Object:
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)")); std::map<gd::String, gd::PropertyDescriptor> properties; properties[_("Looped")] .SetValue(looped ? 'true': 'false') .SetType("boolean") .setLabel(_("Loop the video")); properties[_("Volume")] .SetValue(volume) .SetType("number") .setLabel(_("Video volume (0-100)")); properties[_("Video resource")] .SetValue(videoDataFilename) .SetType("resource") .AddExtraInfo("video") .SetLabel(_('Video resource')); return properties; }
-
Behaviors can also have properties (check example of existing behaviors in
JsExtension.js
or in C++ behaviors) -
Instances of objects can also have custom properties.
Declaring properties is not enough, for behaviors, objects and instances you also need to implement
updateProperty
in JS (orUpdateProperty
in C++), that will be called to update a property when the user changes it in the editor. Use this method to add any validation if needed.
The PropertyDescriptor
has a setType
(or SetType
in C++) method. You can call it with:
"string"
to get a string input field (this is the default),"number"
to get a number input field,"boolean"
to get a checkbox"resource"
to get a resource selector. The resource will be stored as a string, but the editor will show a selector allowing to choose a resource, that will be added to the project.- In this case, you also need to call
addExtraInfo
(AddExtraInfo
in C++) with the type of the resource:"image"
,"audio"
,"font"
or"json"
.
- In this case, you also need to call
- PropertyDescriptor
- A PropertyDescriptor is mapped to a schema that is then displayed by PropertiesEditor.
- A "schema" describes what a PropertiesEditor will display on screen. It's somewhat similar to PropertyDescriptor. The two concepts should be merged at some point.