-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
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
Allow JS plugin environment to run sub-process #2783
Comments
I think one other thing that would be handy is a way to get the location of the current script file (like node's /* global tiled, TextFile, Process */
tiled.registerMapFormat('Subprocess Demo', {
name: 'Subprocess Demo format',
extension: 'txt',
write: function (map, fileName) {
const n = new Process()
// is there a __dirname work-alike for Qt?
n.start(`${__dirname}/myCoolPlugin ${fileName}`)
// need a way to pump JSON map into stdin, here...
n.waitForFinished()
// the plugin will write fileName, on it's own
}
}) You can do cross-platform support by making a file /* global tiled, TextFile, Process */
tiled.registerMapFormat('Subprocess Demo', {
name: 'Subprocess Demo format',
extension: 'txt',
write: function (map, fileName) {
const n = new Process()
n.start(`${__dirname}/${tiled.platform}/${tiled.arch}/myCoolPlugin ${fileName}`)
n.waitForFinished()
}
}) |
I think adding a thin QProcess wrapper would suffice for now. I would take the Process service in Qbs as an example in terms of API. Regarding defining UI in XML or integrating protobuf, I think that goes a little too far right now. Though eventually, I would like to enable building UIs in extensions. I'm not sure if it's worth implementing this with QWidget-based API or whether we could rather make this possible by using QML / Qt Quick. |
No, I just meant that for example protoc uses a known protocol on stdin/out (like in our case that could be JSON) and inkscape implements their plugins primarily in scripts, with a little meta-data. I meant more to think about these as inspiration. I think with a
Yeh, I don't know the details around this, but it seems like it should be pretty built-in to the scripting environment to spawn a config dialog or whatever. I think we should go as thin as possible, and rather than parsing some data-format (like XML) let the user make the widget, however that works easiest in the Qt javascript env. Would this kind of thing already work in the plugin API?: const dialog = Qt.createComponent("config.qml") Again, maybe |
Hmm, it actually works, but you need to create a window and actually instantiate the component. I created a file called import QtQuick.Window 2.12
Window {
x: 100; y: 100; width: 100; height: 100
} Then, in the Tiled console, I typed:
But, while this will work with a local build of Tiled, it does not work with the currently released builds because the relevant Qt Quick libraries are not shipped.
Maybe, but I'm not sure how this would work. It is easy to set it globally before evaluating a script file, but it will not work when it is used in a function when that function is called later. |
I tried this (adding QJSValue ScriptManager::evaluate(const QString &program,
const QString &fileName, int lineNumber)
{
QJSValue globalObject = mEngine->globalObject();
globalObject.setProperty(QStringLiteral("__filename"), fileName);
QJSValue result = mEngine->evaluate(program, fileName, lineNumber);
checkError(result, program);
return result;
} This might be the wrong way, but it outputted another plugin's file: tiled.registerMapFormat('Subprocess Demo', {
name: 'Subprocess Demo format',
extension: 'txt',
write: function (map, fileName) {
console.log('__filename', __filename)
}
})
|
@konsumer Yes, this does not work for the reason I described. :-) |
this works, in the script, which might be a decent solution: const f = __filename
tiled.registerMapFormat('Subprocess Demo', {
name: 'Subprocess Demo format',
extension: 'txt',
write: function (map, fileName) {
console.log(f)
}
}) To avoid confusion, it could be called something other than |
More on the other idea, I put the qml file in the plugin dir, and used it with the /* global tiled, Qt, FileInfo */
const f = __filename
tiled.registerMapFormat('Subprocess Demo', {
name: 'Subprocess Demo format',
extension: 'txt',
write: function (map, fileName) {
console.log(FileInfo.path(f))
const windowComponent = Qt.createComponent(`${FileInfo.path(f)}/window.qml`)
const window = windowComponent.createObject()
window.visible = true
}
}) |
@konsumer That's great! So, the main challenge with supporting this will be to adjust the various release packages to include the necessary Qt Quick plugins. Regarding |
Yeh, for sure. It's cool it works locally, though. I am imagining some really sweet plugin config UIs that are pretty easy to put together.
I just meant because node has the |
Yeah. And, in my patch I delete the property after evaluation, which makes it throw an error when you try to use it when you can't. I think that'll be enough. |
Yep, just saw that. I think you're right. |
I'm also wondering if any interop can be built using javascript extensions. Was thinking about:
What I tried and thought of so far:
@bjorn Is it possible to schedule code in javascript extensions in Tiled? Create thread? Work with sockets? Sorry, I'm new to javascript. Need help understanding which way to go. @konsumer Tell me please, what's your progress? Looks, like you are trying to achieve some form of interop too. But I don't quite understand what you were able to achieve. Context: I wrote a program (libgdx, java) which works with tmx (postprocessing, updating file and special printing). It launches Tiled to edit tmx. Currently one launches another through CLI (java - Process; tiled - using command which launch mine program through CLI) Tiled v. 1.3.5 |
It's not really interop, just running a sub-process. Maybe it would work better if you made your program just watch for file changes? Then you could reload on change, and I think it would acheive what you are going for. It would be a totally separate program, but update on save. |
It would be handy if we could spawn a CLI program, for really simple plugins that just wrap some other existing tool. This would allow people to mostly write plugins in whatever language they like, or whatever is already made, as most languages have a way to make a CLI program (stdio/stdout, file reading/writing, etc.)
This is related to #2780 and I'd like to add it in a similar fashion to
ScriptFileInfo
.Some examples of plugin systems that use CLI programs to do fancy stuff, that we might get inspiration from:
I imagine in it's simplest form, it would just be a thin wrapper for QProcess. So you could something like this (without any async stuff):
In this form, if the user liked go, ruby, python, nodejs, C#, C++, etc, better than Qt-JS, they could use it, as long as their users can run their thing. They still have to write a little wrapper in Qt-JS, but I think that's ok (and sort of takes the place of XML meta-data file in inkscape plugins.) Plugin-makers that wish to maintain maximum compatibility for end-users (no installing nodejs, python, being a windows/posix user, etc) should opt for all Qt-JS plugins, but if the plugin needs to do stuff in some other language, it's possible.
What do you think?
The text was updated successfully, but these errors were encountered: