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 @@ -25,6 +25,7 @@
* Fixed alpha component of tint color not applying correctly to opaque images (by Roland Helmerichs, #4310)
* Scripting: Added API for custom property types (with dogboydog, #3971)
* Scripting: Added TileMap.chunkSize and TileMap.compressionLevel properties
* Scripting: Added tiled.session to read and write session properties (by Kanishka, #4345)
* AutoMapping: Don't match rules based on empty input indexes
* AutoMapping: Optimized reloading of rule maps and load rule maps on-demand
* tBIN plugin: Added support for the tIDE XML format (by Casey Warrington, #4308)
Expand Down
112 changes: 107 additions & 5 deletions docs/scripting-doc/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,7 @@ declare namespace Qt {
* Can be created with {@link tiled.cursor} and assigned to {@link
* Tool.cursor}.
*/
class QCursor {}
class QCursor { }

/**
* The base type from which all Qt widgets derive.
Expand Down Expand Up @@ -753,13 +753,13 @@ declare namespace Qt {
/**
* A button which the user can push.
*/
class QPushButton extends QAbstractButton {}
class QPushButton extends QAbstractButton { }

/**
* This type is returned in mainWidget when calling {@link Dialog.addSeparator}.
* Qt documentation [QFrame](https://doc.qt.io/qt-6/qframe.html)
*/
class QFrame extends QWidget {}
class QFrame extends QWidget { }

/**
* This type is returned when calling {@link QButtonGroup.addItem} or {@link QButtonGroup.addItems}.
Expand All @@ -770,7 +770,7 @@ declare namespace Qt {
*
* @since 1.11.1
*/
class QRadioButton extends QAbstractButton {}
class QRadioButton extends QAbstractButton { }

/**
* A group of radio buttons where only one button can be selected.
Expand Down Expand Up @@ -3963,7 +3963,7 @@ declare class WangSet extends TiledObject {
* tiled.log("The color is black!");
* ```
*/
interface color {}
interface color { }

/**
* A container for tiles that can be used by a map.
Expand Down Expand Up @@ -4632,6 +4632,96 @@ declare namespace Tiled {
const Zstandard: CompressionMethod;
}


/**
* Provides access to session-specific settings. The session stores
* per-project preferences like last-used tile sizes, open files, and
* file states.
*
* Values are accessed by their string key (e.g. `"map.tileWidth"`).
*
* ### Known Session Properties
*
* | Key | Type | Default | Description |
* |-----|------|---------|-------------|
* | `"map.orientation"` | `number` (Map.Orientation) | `Map.Orthogonal` | Last used map orientation |
* | `"map.layerDataFormat"` | `number` (Map.LayerDataFormat) | `Map.CSV` | Last used layer data format |
* | `"map.renderOrder"` | `number` (Map.RenderOrder) | `Map.RightDown` | Last used render order |
* | `"map.fixedSize"` | `boolean` | `true` | Whether new maps use a fixed size |
* | `"map.width"` | `number` | `30` | Last used map width (in tiles) |
* | `"map.height"` | `number` | `20` | Last used map height (in tiles) |
* | `"map.tileWidth"` | `number` | `32` | Last used tile width (in pixels) |
* | `"map.tileHeight"` | `number` | `32` | Last used tile height (in pixels) |
* | `"map.lastUsedFormat"` | `string` | `""` | Last used map format |
* | `"map.lastUsedExportFilter"` | `string` | `""` | Last used map export filter |
* | `"tileset.type"` | `number` | `0` | Last used tileset type |
* | `"tileset.embedInMap"` | `boolean` | `false` | Whether to embed tileset in map |
* | `"tileset.useTransparentColor"` | `boolean` | `false` | Whether to use a transparent color |
* | `"tileset.transparentColor"` | `color` | magenta | Transparent color for tilesets |
* | `"tileset.tileSize"` | `size` | `{width: 32, height: 32}` | Last used tileset tile size |
* | `"tileset.spacing"` | `number` | `0` | Last used tileset spacing |
* | `"tileset.margin"` | `number` | `0` | Last used tileset margin |
* | `"tileset.lastUsedFilter"` | `string` | `""` | Last used tileset file filter |
* | `"tileset.lastUsedFormat"` | `string` | `""` | Last used tileset format |
* | `"resizeMap.removeObjects"` | `boolean` | `true` | Remove objects when resizing |
* | `"exportAsImage.visibleLayersOnly"` | `boolean` | `true` | Export only visible layers |
* | `"exportAsImage.useCurrentScale"` | `boolean` | `false` | Use current scale for export |
* | `"exportAsImage.drawTileGrid"` | `boolean` | `false` | Draw tile grid in export |
* | `"exportAsImage.drawObjectLabels"` | `boolean` | `false` | Draw object labels in export |
* | `"exportAsImage.includeBackgroundColor"` | `boolean` | `false` | Include background color in export |
* | `"automapping.whileDrawing"` | `boolean` | `false` | Automap while drawing |
* | `"mapScene.enableWorlds"` | `boolean` | `true` | Enable worlds in map scene |
* | `"textEdit.monospace"` | `boolean` | `true` | Use monospace font in text editor |
* | `"frame.defaultDuration"` | `number` | `100` | Default animation frame duration |
* | `"console.history"` | `string[]` | `[]` | Console command history |
* | `"property.type"` | `string` | `"string"` | Last used property type |
* | `"file.lastUsedOpenFilter"` | `string` | `""` | Last used file open filter |
* | `"loadedWorlds"` | `string[]` | `[]` | List of currently loaded world files |
* | `"lastUsedTilesetExportFilter"` | `string` | `""` | Last used tileset export filter |
* | `"stampsFolder"` | `string` | `"<dataDir>/stamps"` | Directory for tile stamps |
*
* @since 1.12
*/
interface Session {
/**
* Path to the current session file.
*/
readonly fileName: string;

/**
* Returns the session value for the given key, or `defaultValue` if
* the key is not set.
*/
get(key: string, defaultValue?: any): any;

/**
* Sets the session value for the given key.
*/
set(key: string, value: any): void;

/**
* Returns whether the given key is present in the session.
*/
isSet(key: string): boolean;

/**
* Returns the per-file state for the given file name.
*/
fileState(fileName: string): { [key: string]: any };

/**
* Sets the per-file state for the given file name.
*
* **Warning:** This replaces the entire per-file state for the given file.
* To set only a single value, use {@link setFileStateValue} instead.
*/
setFileState(fileName: string, fileState: { [key: string]: any }): void;

/**
* Sets a single value in the per-file state for the given file name.
*/
setFileStateValue(fileName: string, name: string, value: any): void;
}
/**
* The `tiled` module is the main entry point and provides properties,
* functions and signals which are documented below.
Expand Down Expand Up @@ -4767,6 +4857,18 @@ declare namespace tiled {
*/
export const tilesetEditor: TilesetEditor;

/**
* Provides access to the current session, allowing scripts to read and
* write session-specific settings like last-used tile size.
*
* In command-line mode (`--evaluate`), no session may be available. In
* that case, methods return safe defaults (empty strings, default
* values, etc.).
*
* @since 1.12
*/
export const session: Session;

/**
* This function can be used to trigger any registered action. This
* includes most actions you would normally trigger through the menu or
Expand Down
2 changes: 2 additions & 0 deletions src/tiled/libtilededitor.qbs
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,8 @@ DynamicLibrary {
"scriptmodule.h",
"scriptprocess.cpp",
"scriptprocess.h",
"scriptsession.cpp",
"scriptsession.h",
"scriptpropertytype.cpp",
"scriptpropertytype.h",
"selectionrectangle.cpp",
Expand Down
7 changes: 7 additions & 0 deletions src/tiled/scriptmodule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include "scriptfileformatwrappers.h"
#include "scriptimage.h"
#include "scriptmanager.h"
#include "scriptsession.h"
#include "tilesetdocument.h"
#include "tileseteditor.h"
#include "worlddocument.h"
Expand All @@ -56,6 +57,7 @@ namespace Tiled {

ScriptModule::ScriptModule(QObject *parent)
: QObject(parent)
, mSession(new ScriptSession(this))
{
// If the script module is only created for command-line use, there will
// not be a DocumentManager instance.
Expand Down Expand Up @@ -240,6 +242,11 @@ MapEditor *ScriptModule::mapEditor() const
return nullptr;
}

ScriptSession *ScriptModule::session() const
{
return mSession;
}

QColor ScriptModule::color(const QString &name) const
{
#if QT_VERSION < QT_VERSION_CHECK(6, 4, 0)
Expand Down
5 changes: 5 additions & 0 deletions src/tiled/scriptmodule.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class EditableAsset;
class MapEditor;
class ScriptImage;
class ScriptMapFormatWrapper;
class ScriptSession;
class ScriptTilesetFormatWrapper;
class ScriptedAction;
class ScriptedMapFormat;
Expand Down Expand Up @@ -70,6 +71,7 @@ class ScriptModule : public QObject
Q_PROPERTY(Tiled::EditableAsset *activeAsset READ activeAsset WRITE setActiveAsset NOTIFY activeAssetChanged)
Q_PROPERTY(QList<QObject*> openAssets READ openAssets)
Q_PROPERTY(Tiled::EditableAsset *project READ project)
Q_PROPERTY(Tiled::ScriptSession *session READ session)

Q_PROPERTY(Tiled::MapEditor *mapEditor READ mapEditor)
Q_PROPERTY(Tiled::TilesetEditor *tilesetEditor READ tilesetEditor)
Expand Down Expand Up @@ -105,6 +107,8 @@ class ScriptModule : public QObject
TilesetEditor *tilesetEditor() const;
MapEditor *mapEditor() const;

ScriptSession *session() const;

Q_INVOKABLE QColor color(const QString &name) const;
Q_INVOKABLE QColor color(float r, float g, float b, float a = 1.0f) const;
Q_INVOKABLE Tiled::FilePath filePath(const QUrl &path) const;
Expand Down Expand Up @@ -194,6 +198,7 @@ public slots:
std::map<Id, std::unique_ptr<ScriptedTool>> mRegisteredTools;

QStringList mScriptArguments;
ScriptSession *mSession = nullptr;
};

inline bool ScriptModule::versionLessThan(const QString &a)
Expand Down
90 changes: 90 additions & 0 deletions src/tiled/scriptsession.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/*
* scriptsession.cpp
* Copyright 2026, Kanishka
*
* This file is part of Tiled.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include "scriptsession.h"

#include "session.h"

namespace Tiled {

ScriptSession::ScriptSession(QObject *parent)
: QObject(parent)
{}

QString ScriptSession::fileName() const
{
if (!Session::hasCurrent())
return QString();
return Session::current().fileName();
}

QVariant ScriptSession::get(const QString &key,
const QVariant &defaultValue) const
{
if (!Session::hasCurrent())
return defaultValue;

const QByteArray latin1Key = key.toLatin1();
auto &session = Session::current();

return session.get<QVariant>(latin1Key.constData(), defaultValue);
}

void ScriptSession::set(const QString &key, const QVariant &value)
{
if (!Session::hasCurrent())
return;
Session::current().set(key.toLatin1().constData(), value);
}

bool ScriptSession::isSet(const QString &key) const
{
if (!Session::hasCurrent())
return false;
return Session::current().isSet(key.toLatin1().constData());
}

QVariantMap ScriptSession::fileState(const QString &fileName) const
{
if (!Session::hasCurrent())
return {};
return Session::current().fileState(fileName);
}

void ScriptSession::setFileState(const QString &fileName,
const QVariantMap &fileState)
{
if (!Session::hasCurrent())
return;
Session::current().setFileState(fileName, fileState);
}

void ScriptSession::setFileStateValue(const QString &fileName,
const QString &name,
const QVariant &value)
{
if (!Session::hasCurrent())
return;
Session::current().setFileStateValue(fileName, name, value);
}

} // namespace Tiled

#include "moc_scriptsession.cpp"
59 changes: 59 additions & 0 deletions src/tiled/scriptsession.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* scriptsession.h
* Copyright 2026, Kanishka
*
* This file is part of Tiled.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/

#pragma once

#include <QObject>
#include <QVariant>
#include <QVariantMap>

namespace Tiled {

/**
* Exposes the current Session to the scripting API as tiled.session.
*
* Provides generic get/set access to session values by their string key,
* as well as access to per-file states.
*/
class ScriptSession : public QObject
{
Q_OBJECT

Q_PROPERTY(QString fileName READ fileName)

public:
explicit ScriptSession(QObject *parent = nullptr);

QString fileName() const;

Q_INVOKABLE QVariant get(const QString &key,
const QVariant &defaultValue = QVariant()) const;
Q_INVOKABLE void set(const QString &key, const QVariant &value);
Q_INVOKABLE bool isSet(const QString &key) const;

Q_INVOKABLE QVariantMap fileState(const QString &fileName) const;
Q_INVOKABLE void setFileState(const QString &fileName,
const QVariantMap &fileState);
Q_INVOKABLE void setFileStateValue(const QString &fileName,
const QString &name,
const QVariant &value);
};

} // namespace Tiled
1 change: 1 addition & 0 deletions src/tiled/session.h
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@ class TILED_EDITOR_EXPORT Session : protected FileHelper

static Session &initialize();
static Session &current();
static bool hasCurrent() { return mCurrent != nullptr; }
static Session &switchCurrent(const QString &fileName);
static void deinitialize();

Expand Down