Skip to content

Adds Python scriptable general purpose import/export plugin #415

Merged
merged 40 commits into from Apr 20, 2013

4 participants

@stt
stt commented Apr 4, 2013

So, I've been sitting on this for about a year due to lack of better log output mechanism than printing to stdout, that better mechanism is now implemented as ConsoleDock.

To the uninitiated, a brief overview:

What it is

Allows adding new map filetypes as python scripts in ~/.tiled/ directory.

What it does

Map import and export with tilesets, layers and objects.
There are couple of scripts in the fork, cleanest of which at the moment is Mappy support, that could still use addition of exporting before being considered for public consumption.
A note about export; as Tiled plugins are loaded only once, some details of maps can be stored in the interpreter state while importing a map and then recalled for reintegration when exporting the map back to it's original format.

Runs on

At least Windows 7 and Linux (Ubuntu/Arch Linux)

It requires

  • Python 2.x (realistically >=2.6 which is 5y old, but no version check is done), Tiled of course still runs normally if no usable version of python is found

Personally I favor a system wide installation of python, but it was tested that is not needed if python27.dll (on windows) and python27.zip are copied to the Tiled installation directory (this is combined size of 3.5MB).

Adding support for 3.x was considered and doesn't look like too much work (it should even be able to be supported by the same plugin, taken that the scripts would be loaded from separate directories), but I may not have time to take this on for couple of months.

stt and others added some commits Feb 11, 2012
@stt stt Added python scripting support 80ae482
@stt stt Build dependency now only if pkg-config or python-config present da9a6ef
@stt stt Some cleanup, use QDirIterator 61fafe3
@stt stt Cleanup b91fc2e
@bjorn Exclude Python plugin project entirely when no Python is found
Signed-off-by: Samuli Tuomola <samuli.tuomola@gmail.com>
e0b4ea6
@stt stt Some clarification 152cf60
@stt stt Mappy .FMP v0.3-1.0 import support 6ab43a5
@stt stt Some refactoring 7fe6d5d
@stt stt Now works on Windows 7f5d5e4
@stt stt Added QImage+QColor bindings, and transparent mappy tilesets 3c7ca34
@stt stt Adds QRgb vector container and QImage setColorTable binding e8809ed
@stt stt Use indexed colormap for 8bit images, faster reading b352e46
@stt stt Comma now matches C-style shorthand declaration, also a way to provid…
…e raw data to substructs
bf82540
@stt stt Adds ability to read interleaved LBM images without libraries 7cea90c
@stt stt Some cleanup (keep forgetting windows' special needs) 22ea826
@stt stt Rewrote the plugin w/o callbacks and updated scripts.
Notes:
- fotf now loads most levels with correct tilesets
- Lacks testing in windows
445b05f
@stt stt Added map property + tileset transparency etc bindings
Also layer/objgroup support.
Exposing tilelayer.cell classes' member "tile" produces a nasty warning
from pybindgen, seems to work so far though.
15694f9
@stt stt Write support fixed
Supports export only to same script that loaded the map.
4375b21
@stt stt Added Pekka Kana 2 map import + partial export 2b8ad98
@stt stt Added Windows console window for script output
Also pk2 binary filemode
5f50bf5
@stt stt Added initial zSNES save state import script 3b6a404
@stt stt Support for imagelayers c44841d
@stt stt Couple of fixes 0fab5cd
@stt stt Find bounding box, test imagelayer, load sprites a40dd47
@stt stt Add sprites as mapobjects 552ce70
@stt stt Object ownerships, QPixmap width/height 66c14f8
@stt stt Fixed windows console error output
Could've sworn it used to work without redirect on python side though.
99c4567
@stt stt Let plugins cleanup after themselves when quitting b38dd75
@stt stt Added QFileDialog binding ecd30f2
@stt stt Divided Qt bindings into a submodule c5e082c
@stt stt Should use PyObject rather than PyEval functions 2c3ea4a
@stt stt MapObject's tile now accessed through cell() 2deebf4
@stt stt Added platform agnostic console window 64c810a
@stt stt Console changes, now in color 4b9f712
@stt stt Small fixes 456e08e
@stt stt Small fixes e98823d
@stt stt Dialog->dock widget and Console->LoggingInterface 9b13905
@stt stt Disable PEP370 + some cleanup 742e956
@stt stt Rolled back b38dd75 b5f4689
@stt stt Pass the ownership of the map object
Shouldn't try to free the wrapper yet though as layers are still owned by
it. The wrappers leak so (re)opening a lot of maps may end up consuming
more memory than actually needed, should look into this.
Anyway, it's not script writer's responsibility to manage references.
d3ae074
@bjorn bjorn commented on the diff Apr 20, 2013
src/libtiled/logginginterface.h
+
+namespace Tiled {
+
+/**
+ * An interface to be implemented by classes that want to signal
+ * the message console.
+ */
+class LoggingInterface
+{
+ public:
+ enum OutputType {
+ INFO, ERROR
+ };
+
+ virtual void log(OutputType type, const QString) = 0;
+};
@bjorn
Owner
bjorn added a note Apr 20, 2013

This is kind of strange, because the log method is not used from Tiled but is just forced to be implemented by the plugin, and the only way for it to work is for the plugin to emit signals with a signature that you can only find in consoledock.cpp.

I think the interface is fine, but I think it should be implemented by Tiled, not by the plugin. Then, a function setLogger(LoggingInterface *) for example can be added to MapWriterInterface and MapReaderInterface. Maybe with a default implementation that does nothing, to avoid having to add that to all existing plugins (though I'm sure some existing plugins could use this interface as well).

The ConsoleDock can then implement this interface, query all map readers and writers and set itself as their logger.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@bjorn
Owner
bjorn commented Apr 20, 2013

Noticed this in the Debug Console, an error?

-- Reloading zst
TypeError: issubclass() arg 1 must be a class
@bjorn
Owner
bjorn commented Apr 20, 2013

The plugin crashes (along with Tiled), when I try to open the example map smooth.fmp included with MappyWin32 V1.4.23.

0   QMap<QString, QString>::detach  qmap.h  205 0x7fffe5f956a6  
1   QMap<QString, QString>::insert  qmap.h  562 0x7fffe5f9490a  
2   Tiled::Object::setProperty  object.h    99  0x7fffe5f94651  
3   Python::PythonPlugin::read  pythonplugin.cpp    267 0x7fffe5f9345a  
4   Tiled::Internal::MainWindow::openFile   mainwindow.cpp  579 0x52f6f0    
...

Edit: looking into this, it seems to be due to an uncaught script exception. After that it will still try to set a __script__ property on the uninitialized Tiled::Map *ret.

I've avoided this with a local change and got the script error from the console:

** Uncaught exception in script **
Traceback (most recent call last):
  File "/home/bjorn/.tiled/mappy.py", line 31, in read
    tset.loadFromImage(readtilegfx(hd, chunks['BGFX'], cmap), "")
  File "/home/bjorn/.tiled/mappy.py", line 93, in readtilegfx
    img.setPixel(tx+x, ty+y, cmap[c])
UnboundLocalError: local variable 'c' referenced before assignment
@bjorn
Owner
bjorn commented Apr 20, 2013

I guess we need to separate the name filters for reading and writing, since at the moment there's no way for the Python plugin to avoid listing the Mappy and zSNES in Save As, even though they do not implement writing.

@bjorn bjorn merged commit d3ae074 into bjorn:master Apr 20, 2013

1 check passed

Details default The Travis build passed
@bjorn
Owner
bjorn commented Apr 20, 2013

@stt As you can see I've merged your branch and simply applied the fix for the potential crash on top (commit 5b290f4). I figured we can solve the issues I found after merging.

So, I hope you will consider my proposal to change around the way the LoggingInterface is used, and I think I will try to find some time to fix the conflict between readable and writable name filters eventually.

@stt
stt commented Apr 20, 2013

Yep, the log interface change you proposed sounds logical.
Think I noticed the crash but forgot to apply a fix, thanks for that.
About the scripts, most of them aren't up to date since I've been wondering should they be hosted somewhere outside of tiled, except for some simple one that demonstrates/tests all the features?
Also a plugin/script version check is something that'd be good to have.

@bjorn
Owner
bjorn commented Apr 20, 2013

I think it's fine that those scripts live alongside Tiled, unless you would personally prefer to maintain them elsewhere.

As for the plugin/script version check, feel free to add one. Sounds like a good idea indeed.

@devnewton

A system wide Python installation is fine for developers and most linux users, but a little hard to provides for artists on OS without packaging system...

@josephharding

Hey guys - just wondering where this feature is in the Tiled release schedule. I'd definitely like to be able to write my own export script in python for Tiled. Thanks!

@bjorn
Owner
bjorn commented Dec 16, 2013

@gyrospike To use this feature you need to use a daily build, since it was added after Tiled 0.9. Not all daily builds have Python support enabled though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.