mapeditor / tiled

Flexible level editor
https://www.mapeditor.org/
Other
11.13k stars 1.75k forks source link

Scripting API for templates and template references #2664

Open bjorn opened 4 years ago

bjorn commented 4 years ago

An object may be instantiated based on a template, stored in a separate file. Currently, the scripting API (#949) has no access at all to templates and also can't access or change the template reference stored in an object.

It would be expected that the scripting API:

  1. Can access and change the template referenced by an object
  2. Can reset an object or some of its properties, in case they have overridden those of the template
  3. Can access and modify the templates themselves

The first one could be implemented by a filename-based property. The second one could be done by introducing functions to check for and unset overriding properties.

Providing editable access to templates is tricky, due to the way this is implemented in Tiled. Each change to a template currently immediately saves it and the template is not open as a "document". The undo/redo is handled by a dummy MapDocument that wraps the open template in the TemplatesDock. We may need to reconsider how we handle the editing of templates before writing that part of the scripting API.

LtRandolph commented 4 years ago

I'm really happy with my custom js exporter for my game. I've noticed, however, an issue with scripting objects with templates. It seems related to (though perhaps simpler than) this issue as stated.

I have a set of templates for doors in my game. I want to export whether it's a left, right, up, or down door. So I added a string property "Direction" to each template.

But when I access the objects in script and iterate properties, "Direction" isn't listed. I'm pretty sure that's because the property doesn't live on the object; only on the template.

I'm going to poke around in the cpp and see if I can find a clean way to make EditableMapObject read the full list of properties, including inherited values that haven't been overridden. If I find a solution that would do this, would you potentially be interested in a pull request to look it over?

bjorn commented 4 years ago

I'm going to poke around in the cpp and see if I can find a clean way to make EditableMapObject read the full list of properties, including inherited values that haven't been overridden. If I find a solution that would do this, would you potentially be interested in a pull request to look it over?

Sure. Note however, that we need to still be able to determine whether a property is from the object or the template. On the C++ side, we have the following function to get the value of a property, taking into account any inherited values as well:

QVariant Object::inheritedProperty(const QString &name) const

It could be that for scripts a nicer default is to always take inheritance into account, but in that case we need something like JavaScripts hasOwnProperty (and unfortunately we can't call it that because it's already taken by JavaScript :-)).

I'm personally more inclined to solve this issue by exposing the above inheritedProperty and potentially adding inheritedProperties, though I'm not really happy with these names because they seem to indicate that own properties are excluded.

Of course, the issue would also be resolved when we could access the template object, with the slight downside that it makes reading out a resolved property value somewhat clumsy. But exposing the template object is likely not trivial due to lifetime issues (could be returned as a read-only copy to be on the safe side for now).