Skip to content

Commit

Permalink
Scripting: Added Geometry interface with line and ellipse helpers
Browse files Browse the repository at this point in the history
Providing access from scripts to the existing line and ellipse rendering
functions.
  • Loading branch information
bjorn committed Jul 7, 2023
1 parent cb4c33c commit 9ebf7ac
Show file tree
Hide file tree
Showing 7 changed files with 196 additions and 1 deletion.
34 changes: 34 additions & 0 deletions docs/scripting-doc/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1494,6 +1494,40 @@ declare namespace Base64 {
export function decode(data: ArrayBuffer | string): ArrayBuffer;
}

/**
* Provides functions to rasterize lines and ellipses.
*
* @since 1.10.2
*/
declare namespace Geometry {
/**
* Returns the lists of points on a line from `a` to `b`.
*
* When the `manhattan` option (named after "Manhattan distance") is set to
* `true`, the points on the line can't take diagonal steps.
*/
export function pointsOnLine(a: point, b: point, manhattan?: boolean): point[];

/**
* Returns a lists of points on an ellipse, with `center` as the midpoint
* and with the given radii.
*
* May return duplicate points.
*/
export function pointsOnEllipse(center: point, radiusX: number, radiusY: number): point[];

/**
* Returns an elliptical region based on a rectangle.
*/
export function ellipseRegion(rect: rect): region

/**
* Returns an elliptical region based on a rectangle given by x0,y0 (top-left)
* and x1,y1 (bottom-right), inclusive.
*/
export function ellipseRegion(x0: number, y0: number, x1: number, y1: number): region
}

/**
* Offers various operations on file paths, such as turning absolute paths
* into relative ones, splitting a path into its components, and so on.
Expand Down
9 changes: 9 additions & 0 deletions src/tiled/editablemapobject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ EditableMapObject::~EditableMapObject()
EditableManager::instance().remove(this);
}

#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QJSValue EditableMapObject::polygon() const
{
QJSEngine *engine = ScriptManager::instance().engine();
Expand All @@ -77,6 +78,7 @@ QJSValue EditableMapObject::polygon() const

return array;
}
#endif

EditableTile *EditableMapObject::tile() const
{
Expand Down Expand Up @@ -166,6 +168,7 @@ void EditableMapObject::setVisible(bool visible)
setMapObjectProperty(MapObject::VisibleProperty, visible);
}

#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
void EditableMapObject::setPolygon(QJSValue polygonValue)
{
if (!polygonValue.isArray()) {
Expand All @@ -189,6 +192,12 @@ void EditableMapObject::setPolygon(QJSValue polygonValue)
polygon.append(point);
}

setPolygon(polygon);
}
#endif

void EditableMapObject::setPolygon(const QPolygonF &polygon)
{
if (Document *doc = document()) {
asset()->push(new ChangePolygon(doc, mapObject(), polygon));
} else if (!checkReadOnly()) {
Expand Down
18 changes: 18 additions & 0 deletions src/tiled/editablemapobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,11 @@ class EditableMapObject : public EditableObject
Q_PROPERTY(QSizeF size READ size WRITE setSize)
Q_PROPERTY(qreal rotation READ rotation WRITE setRotation)
Q_PROPERTY(bool visible READ isVisible WRITE setVisible)
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
Q_PROPERTY(QJSValue polygon READ polygon WRITE setPolygon)
#else
Q_PROPERTY(QList<QPointF> polygon READ polygon WRITE setPolygon)
#endif
Q_PROPERTY(QString text READ text WRITE setText)
Q_PROPERTY(Tiled::Font font READ font WRITE setFont)
Q_PROPERTY(Qt::Alignment textAlignment READ textAlignment WRITE setTextAlignment)
Expand Down Expand Up @@ -115,7 +119,11 @@ class EditableMapObject : public EditableObject
QSizeF size() const;
qreal rotation() const;
bool isVisible() const;
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QJSValue polygon() const;
#else
const QPolygonF &polygon() const;
#endif
QString text() const;
Font font() const;
Qt::Alignment textAlignment() const;
Expand Down Expand Up @@ -146,7 +154,10 @@ public slots:
void setSize(QSizeF size);
void setRotation(qreal rotation);
void setVisible(bool visible);
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
void setPolygon(QJSValue polygon);
#endif
void setPolygon(const QPolygonF &polygon);
void setText(const QString &text);
void setFont(const Font &font);
void setTextAlignment(Qt::Alignment textAlignment);
Expand Down Expand Up @@ -219,6 +230,13 @@ inline bool EditableMapObject::isVisible() const
return mapObject()->isVisible();
}

#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
inline const QPolygonF &EditableMapObject::polygon() const
{
return mapObject()->polygon();
}
#endif

inline QString EditableMapObject::text() const
{
return mapObject()->textData().text;
Expand Down
2 changes: 2 additions & 0 deletions src/tiled/libtilededitor.qbs
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,8 @@ DynamicLibrary {
"scriptfileformatwrappers.h",
"scriptfileinfo.cpp",
"scriptfileinfo.h",
"scriptgeometry.cpp",
"scriptgeometry.h",
"scriptimage.cpp",
"scriptimage.h",
"scriptmanager.cpp",
Expand Down
100 changes: 100 additions & 0 deletions src/tiled/scriptgeometry.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*
* scriptgeometry.h
* Copyright 2023, Thorbjørn Lindeijer <[email protected]>
*
* 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 "scriptgeometry.h"

#include "geometry.h"
#include "regionvaluetype.h"

#include <QJSEngine>

namespace Tiled {

/**
* This class makes select geometry functions available to the scripting API.
*/
class ScriptGeometry : public QObject
{
Q_OBJECT

public:
explicit ScriptGeometry(QObject *parent = nullptr)
: QObject(parent)
{}

#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
Q_INVOKABLE QJSValue pointsOnLine(QPoint a, QPoint b, bool manhattan = false);
Q_INVOKABLE QJSValue pointsOnEllipse(QPoint center, int radiusX, int radiusY);
#else
Q_INVOKABLE QVector<QPoint> pointsOnLine(QPoint a, QPoint b, bool manhattan = false)
{ return Tiled::pointsOnLine(a, b, manhattan); }

Q_INVOKABLE QVector<QPoint> pointsOnEllipse(QPoint center, int radiusX, int radiusY)
{ return Tiled::pointsOnEllipse(center, radiusX, radiusY); }
#endif

Q_INVOKABLE Tiled::RegionValueType ellipseRegion(QRect rect)
{ return RegionValueType { Tiled::ellipseRegion(rect) }; }

Q_INVOKABLE Tiled::RegionValueType ellipseRegion(int x0, int y0, int x1, int y1)
{ return RegionValueType { Tiled::ellipseRegion(x0, y0, x1, y1) }; }
};

#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
static QJSValue toJSValue(const QVector<QPoint> &points, QJSEngine *engine)
{
if (!engine)
return QJSValue();

QJSValue array = engine->newArray(points.size());

for (int i = 0; i < points.size(); ++i) {
QJSValue pointObject = engine->newObject();
pointObject.setProperty(QStringLiteral("x"), points.at(i).x());
pointObject.setProperty(QStringLiteral("y"), points.at(i).y());
array.setProperty(i, pointObject);
}

return array;
}

QJSValue ScriptGeometry::pointsOnLine(QPoint a, QPoint b, bool manhattan)
{
return toJSValue(Tiled::pointsOnLine(a, b, manhattan),
qjsEngine(this));
}

QJSValue ScriptGeometry::pointsOnEllipse(QPoint center, int radiusX, int radiusY)
{
return toJSValue(Tiled::pointsOnEllipse(center, radiusX, radiusY),
qjsEngine(this));
}
#endif

void registerGeometry(QJSEngine *jsEngine)
{
jsEngine->globalObject().setProperty(QStringLiteral("Geometry"),
jsEngine->newQObject(new ScriptGeometry));

}

} // namespace Tiled

#include "scriptgeometry.moc"
29 changes: 29 additions & 0 deletions src/tiled/scriptgeometry.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* scriptgeometry.h
* Copyright 2023, Thorbjørn Lindeijer <[email protected]>
*
* 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

class QJSEngine;

namespace Tiled {

void registerGeometry(QJSEngine *jsEngine);

} // namespace Tiled
5 changes: 4 additions & 1 deletion src/tiled/scriptmanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
*/

#include "scriptmanager.h"

#include "editablegrouplayer.h"
#include "editableimagelayer.h"
#include "editablemap.h"
Expand All @@ -37,15 +38,16 @@
#include "projectmanager.h"
#include "regionvaluetype.h"
#include "scriptbase64.h"
#include "scriptdialog.h"
#include "scriptedaction.h"
#include "scriptedtool.h"
#include "scriptfile.h"
#include "scriptfileformatwrappers.h"
#include "scriptfileinfo.h"
#include "scriptgeometry.h"
#include "scriptimage.h"
#include "scriptmodule.h"
#include "scriptprocess.h"
#include "scriptdialog.h"
#include "tilecollisiondock.h"
#include "tilelayer.h"
#include "tilelayeredit.h"
Expand Down Expand Up @@ -405,6 +407,7 @@ void ScriptManager::initialize()
registerDialog(engine);
registerFile(engine);
registerFileInfo(engine);
registerGeometry(engine);
registerProcess(engine);
loadExtensions();
}
Expand Down

0 comments on commit 9ebf7ac

Please sign in to comment.