Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Give scripts access to existing file formats #2716

Merged
merged 12 commits into from
Jan 7, 2020

Conversation

Phlosioneer
Copy link
Contributor

Scripts can now call pre-defined map/tileset formats, and can query what
map/tileset formats are available. Closes #2696.

Still need to write documentation for the new APIs.

I wasn't able to get QJSEngine to accept actual ScriptTilesetFormatWrapper
return values, so functions that return those use QObject instead. Same
applies to ScriptMapFormatWrapper.

Suggestions of better names for ScriptTilesetFormatWrapper/ScriptMapFormatWrapper are welcome.

@Phlosioneer
Copy link
Contributor Author

@bjorn Any idea why returning the custom types doesn't work? I did the Q_DECLARE_METATYPE stuff and the qRegisterMetaType as well. I spent like, 4 hours last night going through the Qt codebase to figure out where the issue was. It turns out that, in the current Qt implementation at least, Q_DECLARE_METATYPE is a no-op for classes that inherit from QObject. qRegisterMetaType has nothing to do with QQmlEngine stuff as far as I can tell... I'm actually able to comment out the qRegisterMetaType for some objects (such as ScriptTextFile) and scripting with it continues to work fine.

I think there's an extra step or condition I'm missing. I just couldn't manage to find it. The code that throws the error eventually checks QPropertyCache, and that was difficult to trace back farther, so I can't tell where along the way it comes up with QMetaType::Undefined for the Q_INVOKABLE's return type.

@bjorn
Copy link
Member

bjorn commented Dec 29, 2019

Any idea why returning the custom types doesn't work? I did the Q_DECLARE_METATYPE stuff and the qRegisterMetaType as well.

The other thing that frequently happens to me as well, is that the type is not recognized because it is in a namespace. That is because if you use Q_INVOKABLE or if you use a type in a Q_PROPERTY, the returned type is encoded by string somewhere and later looked up again. In that case, you need to use "Tiled::EditableSomething" for example instead of just "EditableSomething" even if the compiler will understand the type either way.

@Phlosioneer
Copy link
Contributor Author

Thanks, that fixed it! I'll remember that for the future.

@Phlosioneer
Copy link
Contributor Author

This is now blocked on #2720 , to avoid some messy merge conflicts in the scripting API reference.

Copy link
Member

@bjorn bjorn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice addition! I've left a number of inline comments.

It's too bad we need those wrappers even though the original objects derive from QObject, which as far as I understand is simply because we need to work with editable pointers rather than "raw" maps and tilesets. One day I hope to find a way to unify this, but for now the wrapper is a good solution (besides, it's not the only difference, there's also the different ways of reporting errors...).

src/tiled/scriptmodule.cpp Outdated Show resolved Hide resolved
src/tiled/scriptfileformatwrappers.h Outdated Show resolved Hide resolved
src/tiled/scriptfileformatwrappers.cpp Outdated Show resolved Hide resolved
src/tiled/scriptfileformatwrappers.cpp Outdated Show resolved Hide resolved
src/tiled/scriptfileformatwrappers.cpp Outdated Show resolved Hide resolved
src/tiled/scriptmodule.cpp Outdated Show resolved Hide resolved
src/tiled/scriptmodule.h Outdated Show resolved Hide resolved
src/tiled/scriptfileformatwrappers.cpp Outdated Show resolved Hide resolved
src/tiled/scriptfileformatwrappers.h Outdated Show resolved Hide resolved
src/tiled/scriptfileformatwrappers.cpp Outdated Show resolved Hide resolved
Scripts can now call pre-defined map/tileset formats, and can query what
map/tileset formats are available. Closes mapeditor#2696.

Still need to write documentation for the new APIs.

I wasn't able to get QJSEngine to accept actual ScriptTilesetFormatWrapper
return values, so functions that return those use QObject instead. Same
applies to ScriptMapFormatWrapper.
Qt requires a namespace to resove a class name into a metatype correctly.
It seems to do a string comparison at some point in its code against the
actual symbol written as the return type for a Q_INVOKABLE function,
ignoring how that symbol resoves.
Also fixed a bug making `read` fail (unrecognized return type).
@Phlosioneer Phlosioneer force-pushed the 2696-access-other-file-loaders branch from 0ea6dee to ce63b59 Compare December 31, 2019 01:44
@Phlosioneer Phlosioneer marked this pull request as ready for review December 31, 2019 02:36
Copy link
Member

@bjorn bjorn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the adjustments! I've made some additional inline comments.

Also, the read and write function documentations note that an error will be thrown if the operation is not supported, but the wrapper does not check those flags.

src/tiled/scriptmodule.cpp Outdated Show resolved Hide resolved
docs/reference/scripting.rst Outdated Show resolved Hide resolved
src/tiled/scriptfileformatwrappers.cpp Outdated Show resolved Hide resolved
src/tiled/scriptfileformatwrappers.cpp Outdated Show resolved Hide resolved
@Phlosioneer
Copy link
Contributor Author

The MapFormat/TilesetFormat interface already throws the error if control reaches a non-overrided function. However, thinking about it, that may not be an actual javascript error; it might just be a message in the console? I'll check.

@Phlosioneer
Copy link
Contributor Author

Github won't let me respond to the last two messages you left, so I'll reply here:

I would prefer to do without any special handling for scripted map/tileset formats. And also to replace the name and extension properties with a nameFilter property, to match the FileFormat interface.

In that case I would rather not expose the nameFilter at all, then. It's not useful for scripts, we already have the supportsFile function.

Phlosioneer and others added 7 commits January 2, 2020 19:41
Removed `name` and `extension` properties. Added checks for whether
a file format is able to read/write.
There are really only two built-in formats, which are the 'tmx' and
'tsx' formats. All the others are added by plugins which can be disabled
by the user.

Regardless, I don't see much value in documenting this list of formats
and then having to maintain those lists (which will surely be
forgotten).
@bjorn bjorn merged commit 157605b into mapeditor:master Jan 7, 2020
@bjorn
Copy link
Member

bjorn commented Jan 7, 2020

Nice work, thanks!

@Phlosioneer
Copy link
Contributor Author

Phlosioneer commented Jan 7, 2020

Uh, your commits didn't pass the compile tests. Though it seems to be a CI error.

@bjorn
Copy link
Member

bjorn commented Jan 7, 2020

@Phlosioneer Heh, they failed because the pull request was already closed when they started.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Scripting API: Access other file loaders
2 participants