diff --git a/NEWS.md b/NEWS.md index a2e9881f5d..c0948da657 100644 --- a/NEWS.md +++ b/NEWS.md @@ -14,6 +14,7 @@ * Scripting: Added tiled.projectFilePath * Scripting: Added tiled.versionLessThan * Scripting: Added TileMap.toImage (#3519) +* Scripting: Added Tool.targetLayerType (#3248) * Scripting: Added region.contiguousRegions() (#3576) * Scripting: Allow assigning null to Tile.objectGroup (by Logan Higinbotham, #3495) * Scripting: Allow changing the items in a combo box added to a dialog diff --git a/docs/scripting-doc/index.d.ts b/docs/scripting-doc/index.d.ts index ea1b827e89..bf7cb50d27 100644 --- a/docs/scripting-doc/index.d.ts +++ b/docs/scripting-doc/index.d.ts @@ -2100,6 +2100,11 @@ declare class Tile extends TiledObject { * The base class of the various supported layer types. */ declare class Layer extends TiledObject { + static readonly TileLayerType: number + static readonly ObjectGroupType: number + static readonly ImageLayerType: number + static readonly GroupLayerType: number + /** * Unique (map-wide) ID of the layer * @@ -3271,6 +3276,18 @@ interface Tool { */ usesWangSets: boolean; + /** + * The target layer type for which this tool should be enabled. A convenient + * alternative to overriding {@link updateEnabledState}. + * + * The value can be any combination of the layer types + * {@link Layer.TileLayerType}, {@link Layer.ObjectGroupType}, + * {@link Layer.ImageLayerType} and {@link Layer.GroupLayerType}. + * + * @since 1.10 + */ + targetLayerType: number; + /** * Called when the tool was activated. */ diff --git a/src/tiled/abstractobjecttool.cpp b/src/tiled/abstractobjecttool.cpp index 0510b781cb..1e11a764d9 100644 --- a/src/tiled/abstractobjecttool.cpp +++ b/src/tiled/abstractobjecttool.cpp @@ -94,6 +94,8 @@ AbstractObjectTool::AbstractObjectTool(Id id, QObject *parent) : AbstractTool(id, name, icon, shortcut, parent) { + setTargetLayerType(Layer::ObjectGroupType); + QIcon flipHorizontalIcon(QLatin1String(":images/24/flip-horizontal.png")); QIcon flipVerticalIcon(QLatin1String(":images/24/flip-vertical.png")); QIcon rotateLeftIcon(QLatin1String(":images/24/rotate-left.png")); @@ -241,11 +243,6 @@ void AbstractObjectTool::filterMapObjects(QList &mapObjects) const } } -void AbstractObjectTool::updateEnabledState() -{ - setEnabled(currentObjectGroup() != nullptr); -} - ObjectGroup *AbstractObjectTool::currentObjectGroup() const { if (!mapDocument()) diff --git a/src/tiled/abstractobjecttool.h b/src/tiled/abstractobjecttool.h index 8cca5ce5c1..67d2d58c54 100644 --- a/src/tiled/abstractobjecttool.h +++ b/src/tiled/abstractobjecttool.h @@ -75,12 +75,6 @@ class AbstractObjectTool : public AbstractTool void filterMapObjects(QList &mapObjects) const; protected: - /** - * Overridden to only enable this tool when the currently selected layer is - * an object group. - */ - void updateEnabledState() override; - ObjectGroup *currentObjectGroup() const; QList mapObjectsAt(const QPointF &pos) const; MapObject *topMostMapObjectAt(const QPointF &pos) const; diff --git a/src/tiled/abstracttiletool.cpp b/src/tiled/abstracttiletool.cpp index e67961a104..77a38062c2 100644 --- a/src/tiled/abstracttiletool.cpp +++ b/src/tiled/abstracttiletool.cpp @@ -25,7 +25,6 @@ #include "mapdocument.h" #include "maprenderer.h" #include "mapscene.h" -#include "tile.h" #include "tilelayer.h" #include "tilestamp.h" @@ -45,6 +44,8 @@ AbstractTileTool::AbstractTileTool(Id id, , mBrushItem(brushItem) , mBrushVisible(false) { + setTargetLayerType(Layer::TileLayerType); + if (!mBrushItem) mBrushItem = new BrushItem; mBrushItem->setVisible(false); @@ -160,7 +161,7 @@ void AbstractTileTool::mapDocumentChanged(MapDocument *oldDocument, void AbstractTileTool::updateEnabledState() { - setEnabled(currentTileLayer() != nullptr); + AbstractTool::updateEnabledState(); updateBrushVisibility(); } @@ -212,6 +213,9 @@ TileLayer *AbstractTileTool::currentTileLayer() const void AbstractTileTool::updateBrushVisibility() { + if (!mBrushItem) + return; + // Show the tile brush only when at least one target layer is visible bool showBrush = false; if (mBrushVisible) { @@ -223,6 +227,7 @@ void AbstractTileTool::updateBrushVisibility() } } } + mBrushItem->setVisible(showBrush); } diff --git a/src/tiled/abstracttool.cpp b/src/tiled/abstracttool.cpp index 69568c3698..7334ab67e5 100644 --- a/src/tiled/abstracttool.cpp +++ b/src/tiled/abstracttool.cpp @@ -105,6 +105,15 @@ void AbstractTool::setVisible(bool visible) emit visibleChanged(visible); } +void AbstractTool::setTargetLayerType(int targetLayerType) +{ + if (mTargetLayerType == targetLayerType) + return; + + mTargetLayerType = targetLayerType; + updateEnabledState(); +} + Tile *AbstractTool::tile() const { return toolManager()->tile(); @@ -170,7 +179,16 @@ void AbstractTool::changeEvent(const ChangeEvent &event) void AbstractTool::updateEnabledState() { - setEnabled(mMapDocument != nullptr); + // By default, no tool is enabled when there is no map selected + bool enabled = mMapDocument != nullptr; + + // If a target layer type is set, check if the current layer matches + if (mTargetLayerType) { + auto layer = currentLayer(); + enabled &= layer && layer->layerType() & mTargetLayerType; + } + + setEnabled(enabled); } Layer *AbstractTool::currentLayer() const diff --git a/src/tiled/abstracttool.h b/src/tiled/abstracttool.h index fb56c71aeb..5632741110 100644 --- a/src/tiled/abstracttool.h +++ b/src/tiled/abstracttool.h @@ -23,6 +23,7 @@ #include "changeevents.h" #include "id.h" +#include "layer.h" #include #include @@ -70,6 +71,7 @@ class AbstractTool : public QObject Q_PROPERTY(bool visible READ isVisible WRITE setVisible NOTIFY visibleChanged) Q_PROPERTY(bool usesSelectedTiles READ usesSelectedTiles WRITE setUsesSelectedTiles) Q_PROPERTY(bool usesWangSets READ usesWangSets WRITE setUsesWangSets) + Q_PROPERTY(int targetLayerType READ targetLayerType WRITE setTargetLayerType) public: /** @@ -111,6 +113,9 @@ class AbstractTool : public QObject bool usesWangSets() const; void setUsesWangSets(bool usesWangSets); + int targetLayerType() const; + void setTargetLayerType(int targetLayerType); + ToolManager *toolManager() const; Tile *tile() const; ObjectTemplate *objectTemplate() const; @@ -231,6 +236,7 @@ class AbstractTool : public QObject bool mVisible = true; bool mUsesSelectedTiles = false; bool mUsesWangSets = false; + int mTargetLayerType = 0; ToolManager *mToolManager = nullptr; MapDocument *mMapDocument = nullptr; @@ -304,6 +310,11 @@ inline void AbstractTool::setUsesWangSets(bool usesWangSets) mUsesWangSets = usesWangSets; } +inline int AbstractTool::targetLayerType() const +{ + return mTargetLayerType; +} + /** * Returns the ToolManager with which this tool is registered, if any. */ diff --git a/src/tiled/editablelayer.h b/src/tiled/editablelayer.h index 684a6a8ad0..c53ba4bfa2 100644 --- a/src/tiled/editablelayer.h +++ b/src/tiled/editablelayer.h @@ -52,6 +52,15 @@ class EditableLayer : public EditableObject Q_PROPERTY(bool isImageLayer READ isImageLayer CONSTANT) public: + // Synchronized with Layer::LayerType + enum TypeFlag { + TileLayerType = 0x01, + ObjectGroupType = 0x02, + ImageLayerType = 0x04, + GroupLayerType = 0x08 + }; + Q_ENUM(TypeFlag) + explicit EditableLayer(std::unique_ptr layer, QObject *parent = nullptr); diff --git a/src/tiled/layeroffsettool.cpp b/src/tiled/layeroffsettool.cpp index 57accec1a3..a91b37b1d9 100644 --- a/src/tiled/layeroffsettool.cpp +++ b/src/tiled/layeroffsettool.cpp @@ -23,7 +23,6 @@ #include "changelayer.h" #include "grouplayer.h" -#include "layermodel.h" #include "mapdocument.h" #include "maprenderer.h" #include "mapscene.h" @@ -47,6 +46,7 @@ LayerOffsetTool::LayerOffsetTool(QObject *parent) , mDragging(false) , mApplyingChange(false) { + setTargetLayerType(Layer::AnyLayerType); } void LayerOffsetTool::mouseEntered() @@ -139,11 +139,6 @@ void LayerOffsetTool::languageChanged() setName(tr("Offset Layers")); } -void LayerOffsetTool::updateEnabledState() -{ - setEnabled(currentLayer()); -} - void LayerOffsetTool::mapDocumentChanged(MapDocument *oldDocument, MapDocument *newDocument) { diff --git a/src/tiled/layeroffsettool.h b/src/tiled/layeroffsettool.h index 9de2e1f590..327f33a1ff 100644 --- a/src/tiled/layeroffsettool.h +++ b/src/tiled/layeroffsettool.h @@ -44,9 +44,6 @@ class LayerOffsetTool : public AbstractTool void languageChanged() override; -protected slots: - void updateEnabledState() override; - protected: void mapDocumentChanged(MapDocument *oldDocument, MapDocument *newDocument) override; diff --git a/src/tiled/scriptedtool.cpp b/src/tiled/scriptedtool.cpp index 45de0fa832..dab62d132f 100644 --- a/src/tiled/scriptedtool.cpp +++ b/src/tiled/scriptedtool.cpp @@ -43,6 +43,8 @@ ScriptedTool::ScriptedTool(Id id, QJSValue object, QObject *parent) : AbstractTileTool(id, QStringLiteral(""), QIcon(), QKeySequence(), nullptr, parent) , mScriptObject(std::move(object)) { + setTargetLayerType(0); // default behavior is not to disable based on current layer + const QJSValue nameProperty = mScriptObject.property(QStringLiteral("name")); if (nameProperty.isString()) setName(nameProperty.toString()); @@ -68,6 +70,10 @@ ScriptedTool::ScriptedTool(Id id, QJSValue object, QObject *parent) if (usesWangSetsProperty.isBool()) setUsesWangSets(usesWangSetsProperty.toBool()); + const QJSValue targetLayerTypeProperty = mScriptObject.property(QStringLiteral("targetLayerType")); + if (targetLayerTypeProperty.isNumber()) + setTargetLayerType(targetLayerTypeProperty.toInt()); + // Make members of ScriptedTool available through the original object auto &scriptManager = ScriptManager::instance(); auto self = scriptManager.engine()->newQObject(this); @@ -302,10 +308,10 @@ void ScriptedTool::updateStatusInfo() void ScriptedTool::updateEnabledState() { if (!call(QStringLiteral("updateEnabledState"))) { - // Skipping AbstractTileTool since we do not want the enabled state to - // automatically depend on any selected tile layers. - AbstractTool::updateEnabledState(); + AbstractTileTool::updateEnabledState(); + return; } + updateBrushVisibility(); }