Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
* Scripting: Added 'tiled.cell' function, 'cell.flags' property and 'TileLayerEdit.setCell' function (#4538)
* Scripting: Added MapObject.resolvedClassName() (by MatusGuy, #4529)
* Scripting: Added Tileset.selectedTilesChanged signal (#4615)
* Scripting: Fixed world scripting APIs to work without the editor (by Shubham Padkonde, #4584)
* Fixed crash when the selection becomes empty while starting a move (#4536)
* Fixed Properties view update on 'Reset Template Instance' and 'Replace With Template' actions
* Fixed restoring of the layout for maximized windows on startup (#4580)
Expand Down
9 changes: 5 additions & 4 deletions docs/reference/support-for-tmx-maps.rst
Original file line number Diff line number Diff line change
Expand Up @@ -327,10 +327,11 @@ HTML5 (multiple engines)
multi-canvas based game rendering library
- `melonJS <http://www.melonjs.org>`__ A lightweight HTML5 game engine
- `Panda 2 <https://www.panda2.io/>`__, a HTML5 Game Development Platform for Mac, Windows and Linux. Has `a plugin for rendering Tiled <https://www.panda2.io/plugins>`__ maps, both orthogonal and isometric.
- `pixi-tiledmap <https://github.com/riebel/pixi-tiledmap>`__ A
loader and renderer for Tiled Maps in `Pixi.JS <https://pixijs.com/>`__
v8+ written in TypeScript. JSON/XML support with no external deps,
full layer-type support, typed API and ESM/CJS dual output.
- `pixi-tiledmap <https://github.com/riebel/pixi-tiledmap>`__ A Tiled map
runtime for `PixiJS <https://pixijs.com/>`__ v8+, written in TypeScript.
TMX/TMJ parsing with no external dependencies, all layer types and
orientations, batched tile rendering, runtime tile editing, procedural
map generation, and export back to Tiled JSON.
- `Phaser <http://www.phaser.io>`__ A fast, free and fun open source
framework supporting both JavaScript and TypeScript (`Tiled
tutorial <http://www.gamedevacademy.org/html5-phaser-tutorial-top-down-games-with-tiled/>`__)
Expand Down
1 change: 1 addition & 0 deletions docs/scripting-doc/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5472,6 +5472,7 @@ declare namespace tiled {

/**
* Load a world contained in a .world file in the path fileName.
* Throws an error if the world could not be loaded.
* @since 1.11
*/
export function loadWorld(fileName: string): void;
Expand Down
12 changes: 5 additions & 7 deletions src/tiled/scriptmodule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,9 @@ ScriptModule::ScriptModule(QObject *parent)
connect(documentManager, &DocumentManager::documentSaved, this, &ScriptModule::documentSaved);
connect(documentManager, &DocumentManager::documentAboutToClose, this, &ScriptModule::documentAboutToClose);
connect(documentManager, &DocumentManager::currentDocumentChanged, this, &ScriptModule::currentDocumentChanged);

connect(&WorldManager::instance(), &WorldManager::worldsChanged, this, &ScriptModule::worldsChanged);
}

connect(&WorldManager::instance(), &WorldManager::worldsChanged, this, &ScriptModule::worldsChanged);
}

ScriptModule::~ScriptModule()
Expand Down Expand Up @@ -756,10 +756,6 @@ QList<QObject *> ScriptModule::worlds() const
{
QList<QObject*> worlds;

auto documentManager = DocumentManager::maybeInstance();
if (!documentManager)
return worlds;

for (auto &worldDocument : WorldManager::instance().worlds())
worlds.append(worldDocument->editable());

Expand All @@ -768,7 +764,9 @@ QList<QObject *> ScriptModule::worlds() const

void ScriptModule::loadWorld(const QString &fileName) const
{
WorldManager::instance().loadWorld(fileName);
QString error;
if (!WorldManager::instance().loadWorld(fileName, &error))
ScriptManager::instance().throwError(error);
}

void ScriptModule::unloadWorld(const QString &fileName) const
Expand Down
10 changes: 10 additions & 0 deletions tests/scriptmodule/scriptmodule.qbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
TiledTest {
name: "test_scriptmodule"

Depends { name: "libtilededitor" }
Depends { name: "Qt.qml" }

files: [
"test_scriptmodule.cpp",
]
}
99 changes: 99 additions & 0 deletions tests/scriptmodule/test_scriptmodule.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
#include "projectmanager.h"
#include "scriptmanager.h"
#include "worldmanager.h"

#include <QJSEngine>
#include <QStandardPaths>
#include <QtTest/QtTest>

#include <memory>

using namespace Tiled;

class test_ScriptModule : public QObject
{
Q_OBJECT

private slots:
void initTestCase();
void cleanupTestCase();
void cleanup();
void worldsWithoutDocumentManager();
void worldsChangedWithoutDocumentManager();
void loadMissingWorld();

private:
std::unique_ptr<ProjectManager> mProjectManager;
};

void test_ScriptModule::initTestCase()
{
QStandardPaths::setTestModeEnabled(true);
mProjectManager = std::make_unique<ProjectManager>();
ScriptManager::instance().ensureInitialized();
}

void test_ScriptModule::cleanupTestCase()
{
ScriptManager::deleteInstance();
mProjectManager.reset();
}

void test_ScriptModule::cleanup()
{
WorldManager::instance().unloadAllWorlds();
}

void test_ScriptModule::worldsWithoutDocumentManager()
{
QTemporaryFile file;
QVERIFY(file.open());
file.write("{\"type\":\"world\",\"maps\":[]}");
file.flush();

auto &manager = ScriptManager::instance();
manager.engine()->globalObject().setProperty(QStringLiteral("testWorldPath"), file.fileName());
const auto result = manager.evaluate(QStringLiteral("tiled.loadWorld(testWorldPath); tiled.worlds.length"));
QVERIFY2(!result.isError(), qPrintable(result.toString()));
QCOMPARE(WorldManager::instance().worlds().size(), 1);
QCOMPARE(result.toInt(), 1);

const auto afterUnload = manager.evaluate(QStringLiteral("tiled.unloadWorld(testWorldPath); tiled.worlds.length"));
QCOMPARE(afterUnload.toInt(), 0);
}

void test_ScriptModule::worldsChangedWithoutDocumentManager()
{
QTemporaryFile file;
QVERIFY(file.open());
file.write("{\"type\":\"world\",\"maps\":[]}");
file.flush();

auto &manager = ScriptManager::instance();
manager.engine()->globalObject().setProperty(QStringLiteral("testWorldPath"), file.fileName());
const auto result = manager.evaluate(QStringLiteral(
"var changes = 0;"
"tiled.worldsChanged.connect(function() { ++changes; });"
"tiled.loadWorld(testWorldPath); changes"));
QVERIFY2(!result.isError(), qPrintable(result.toString()));
QCOMPARE(result.toInt(), 1);

const auto afterUnload = manager.evaluate(QStringLiteral("tiled.unloadAllWorlds(); changes"));
QCOMPARE(afterUnload.toInt(), 2);
}

void test_ScriptModule::loadMissingWorld()
{
QTemporaryDir directory;
QVERIFY(directory.isValid());
auto &manager = ScriptManager::instance();
manager.engine()->globalObject().setProperty(QStringLiteral("testWorldPath"),
directory.filePath(QStringLiteral("missing.world")));
const auto result = manager.evaluate(QStringLiteral("tiled.loadWorld(testWorldPath)"));
QVERIFY(result.isError());
QVERIFY(WorldManager::instance().worlds().isEmpty());
}

QTEST_MAIN(test_ScriptModule)

#include "test_scriptmodule.moc"
1 change: 1 addition & 0 deletions tests/tests.qbs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Project {
"automapping",
"mapreader",
"properties",
"scriptmodule",
"staggeredrenderer",
]
}
Loading