diff --git a/NEWS.md b/NEWS.md index edb06b88b1..4fe0646254 100644 --- a/NEWS.md +++ b/NEWS.md @@ -2,6 +2,7 @@ * Rewritten Properties view to enable direct widget interaction (#4045) * Added support for lists in custom properties (#1493) +* Added capsule object shape (by Jocelyn, #2153) * Allow filtering tilesets by name in the tileset dock (with dogboydog, #4239) * Allow changing the values of number inputs using expressions (with dogboydog, #4234) * Added support for SVG 1.2 / CSS blending modes to layers (#3932) diff --git a/docs/manual/objects.rst b/docs/manual/objects.rst index e9617a2576..3a391bf436 100644 --- a/docs/manual/objects.rst +++ b/docs/manual/objects.rst @@ -37,7 +37,7 @@ to switch to the :ref:`select-objects-tool` tool. Insert Rectangle ~~~~~~~~~~~~~~~~ -Shortcut: ``R`` +Shortcut: ``R`` |insert-rectangle| The rectangle was the first type of object supported by Tiled, which is why objects are rectangles by default in the :doc:`/reference/tmx-map-format`. They @@ -61,7 +61,7 @@ around its position. This is mainly to keep it visible and selectable. Insert Point ~~~~~~~~~~~~~~ -Shortcut: ``I`` +Shortcut: ``I`` |insert-point| Points are the simplest objects you can place on a map. They only represent a location, and cannot be resized or rotated. Simply click on the map to position @@ -72,18 +72,35 @@ a point object. Insert Ellipse ~~~~~~~~~~~~~~ -Shortcut: ``C`` +Shortcut: ``C`` |insert-ellipse| Ellipses work the same way as `rectangles <#insert-rectangle>`__, except that they are rendered as an ellipse. Useful for when your area or collision shape needs to represent a circle or ellipse. + +.. raw:: html + +
Since Tiled 1.12
+ + +.. _insert-capsule-tool: + +Insert Capsule +~~~~~~~~~~~~~~ + +Shortcut: ``Shift+C`` |insert-capsule| + +Capsules work the same way as `rectangles <#insert-rectangle>`__, except +that they are rendered as a capsule. Useful for when your area or +collision shape needs to represent a circle or capsule. + .. _insert-polygon-tool: Insert Polygon ~~~~~~~~~~~~~~ -Shortcut: ``P`` +Shortcut: ``P`` |insert-polygon| Polygons are the most flexible way of defining the shape of an area. They are most commonly used for defining collision shapes. @@ -125,7 +142,7 @@ The :ref:`edit-polygons-tool` tool is used to edit polylines as well. Insert Tile ~~~~~~~~~~~ -Shortcut: ``T`` +Shortcut: ``T`` |insert-tile| Tiles can be inserted as objects to have full flexibility in placing, scaling and rotating the tile image on your map. Like all objects, tile @@ -168,7 +185,7 @@ objects consistent with that of :ref:`rectangle objects Insert Template ~~~~~~~~~~~~~~~ -Shortcut: ``V`` +Shortcut: ``V`` |insert-template| Can be used to quickly insert multiple instances of the template selected in the Templates view. See :ref:`creating-template-instances`. @@ -178,7 +195,7 @@ selected in the Templates view. See :ref:`creating-template-instances`. Insert Text ~~~~~~~~~~~ -Shortcut: ``X`` +Shortcut: ``X`` |insert-text| Text objects can be used to add arbitrary multi-line text to your maps. You can configure various font properties and the wrapping / clipping @@ -190,7 +207,7 @@ the game. Select Objects -------------- -Shortcut: ``S`` +Shortcut: ``S`` |tool-select-objects| When you're not inserting new objects, you're generally using the Select Objects tool. It packs a lot of functionality, which is outlined below. @@ -384,3 +401,14 @@ jump there by right-clicking the property and selecting *Go to Object*. faster by `sponsoring Tiled development `__. The more support I receive the more time I can afford to spend improving Tiled! + + +.. |tool-select-objects| image:: ../../src/tiled/resources/images/22/tool-select-objects.png +.. |insert-rectangle| image:: ../../src/tiled/resources/images/24/insert-rectangle.png +.. |insert-point| image:: ../../src/tiled/resources/images/24/insert-point.png +.. |insert-ellipse| image:: ../../src/tiled/resources/images/24/insert-ellipse.png +.. |insert-capsule| image:: ../../src/tiled/resources/images/24/insert-capsule.png +.. |insert-polygon| image:: ../../src/tiled/resources/images/24/insert-polygon.png +.. |insert-tile| image:: ../../src/tiled/resources/images/24/insert-image.png +.. |insert-template| image:: ../../src/tiled/resources/images/24/insert-template.png +.. |insert-text| image:: ../../src/tiled/resources/images/24/insert-text.png diff --git a/docs/reference/json-map-format.rst b/docs/reference/json-map-format.rst index f7907cc57a..3b316854f1 100644 --- a/docs/reference/json-map-format.rst +++ b/docs/reference/json-map-format.rst @@ -233,6 +233,7 @@ Object :header: Field, Type, Description :widths: 1, 1, 4 + capsule, bool, "Used to mark an object as a capsule" ellipse, bool, "Used to mark an object as an ellipse" gid, int, "Global tile ID, only if object represents a tile" height, double, "Height in pixels." @@ -492,10 +493,10 @@ Tileset wangsets, array, "Array of :ref:`Wang sets ` (since 1.1.5)" Each tileset has a ``firstgid`` (first global ID) property which -tells you the global ID of its first tile (the one with local -tile ID 0). This allows you to map the global IDs back to the -right tileset, and then calculate the local tile ID by -subtracting the ``firstgid`` from the global tile ID. The first +tells you the global ID of its first tile (the one with local +tile ID 0). This allows you to map the global IDs back to the +right tileset, and then calculate the local tile ID by +subtracting the ``firstgid`` from the global tile ID. The first tileset always has a ``firstgid`` value of 1. .. _json-tileset-grid: @@ -769,6 +770,8 @@ Tiled 1.12 * Added ``mode`` property to :ref:`json-layer` to specify the blend mode to use when rendering the layer. +* Added ``capsule`` property to :ref:`json-object`. + Tiled 1.11.1 ~~~~~~~~~~~~ diff --git a/docs/reference/tmx-changelog.rst b/docs/reference/tmx-changelog.rst index 066eb11309..3855063b1a 100644 --- a/docs/reference/tmx-changelog.rst +++ b/docs/reference/tmx-changelog.rst @@ -9,6 +9,16 @@ Tiled 1.12 - Added ``mode`` attribute on :ref:`tmx-layer` to specific its blend mode. +- Added capsule object shape. Same parameters as rectangular objects, + but marked as capsule with a child element: + + .. code:: xml + + + + + + Tiled 1.10 ---------- diff --git a/docs/reference/tmx-map-format.rst b/docs/reference/tmx-map-format.rst index 39b3586ce5..df50932cd0 100644 --- a/docs/reference/tmx-map-format.rst +++ b/docs/reference/tmx-map-format.rst @@ -578,9 +578,9 @@ properties from the specified template, properties saved with the object will have higher priority, i.e. they will override the template properties. -Can contain at most one: :ref:`tmx-properties`, :ref:`tmx-ellipse` (since -0.9), :ref:`tmx-point` (since 1.1), :ref:`tmx-polygon`, :ref:`tmx-polyline`, -:ref:`tmx-text` (since 1.0) +Can contain at most one: :ref:`tmx-properties`, :ref:`tmx-ellipse` (since 0.9), +:ref:`tmx-capsule` (since 1.12), :ref:`tmx-point` (since 1.1), +:ref:`tmx-polygon`, :ref:`tmx-polyline`, :ref:`tmx-text` (since 1.0) .. _tmx-ellipse: @@ -591,6 +591,15 @@ Used to mark an object as an ellipse. The existing ``x``, ``y``, ``width`` and ``height`` attributes are used to determine the size of the ellipse. +.. _tmx-capsule: + + +~~~~~~~~~ + +Used to mark an object as a capsule. The existing ``x``, ``y``, +``width`` and ``height`` attributes are used to determine the size of +the capsule. + .. _tmx-point: diff --git a/src/libtiled/isometricrenderer.cpp b/src/libtiled/isometricrenderer.cpp index a5b6587341..3f85f3feec 100644 --- a/src/libtiled/isometricrenderer.cpp +++ b/src/libtiled/isometricrenderer.cpp @@ -120,6 +120,15 @@ QPainterPath IsometricRenderer::shape(const MapObject *object) const QPainterPath path; switch (object->shape()) { + case MapObject::Capsule: { + QRectF bounds = object->bounds(); + bounds.translate(-alignmentOffset(bounds, object->alignment(map()))); + const qreal rad = std::min(std::abs(bounds.height()), + std::abs(bounds.width())) / 2; + path.addRoundedRect(bounds, rad, rad, Qt::SizeMode::AbsoluteSize); + path = transform().map(path); + break; + } case MapObject::Ellipse: { QRectF bounds = object->bounds(); bounds.translate(-alignmentOffset(bounds, object->alignment(map()))); @@ -166,7 +175,8 @@ QPainterPath IsometricRenderer::interactionShape(const MapObject *object) const } else { switch (object->shape()) { case MapObject::Rectangle: - case MapObject::Ellipse: { + case MapObject::Ellipse: + case MapObject::Capsule: { QRectF bounds = object->bounds(); bounds.translate(-alignmentOffset(bounds, object->alignment(map()))); @@ -404,18 +414,19 @@ void IsometricRenderer::drawMapObject(QPainter *painter, // TODO: Do something sensible to make null-sized objects usable switch (object->shape()) { - case MapObject::Ellipse: { + case MapObject::Ellipse: + case MapObject::Capsule: { const QPolygonF rect = pixelRectToScreenPolygon(bounds); - const QPainterPath ellipse = shape(object); + const QPainterPath path = shape(object); - painter->drawPath(ellipse.translated(shadowOffset)); + painter->drawPath(path.translated(shadowOffset)); painter->drawPolygon(rect.translated(shadowOffset)); painter->setPen(colorPen); painter->drawPolygon(rect); painter->setBrush(brush); - painter->drawPath(ellipse); + painter->drawPath(path); break; } case MapObject::Point: diff --git a/src/libtiled/mapobject.cpp b/src/libtiled/mapobject.cpp index a517801a98..be157ed768 100644 --- a/src/libtiled/mapobject.cpp +++ b/src/libtiled/mapobject.cpp @@ -178,6 +178,7 @@ QRectF MapObject::screenBounds(const MapRenderer &renderer) const } else { switch (mShape) { case MapObject::Ellipse: + case MapObject::Capsule: case MapObject::Rectangle: { QRectF bounds(this->bounds()); align(bounds, alignment(renderer.map())); @@ -491,8 +492,8 @@ void MapObject::flipInScreenCoordinates(FlipDirection direction, const QPointF & } /** - * Rectangles, ellipses and polygons are flipped in "pixel space", the - * coordinate space before isometric projection. + * Rectangles, ellipses, capsules and polygons are flipped in "pixel space", + * the coordinate space before isometric projection. * * NOTE: No attempt to handle rotated shapes on isometric maps is made. The * expectation is that due to their weird handling, nobody really does that diff --git a/src/libtiled/mapobject.h b/src/libtiled/mapobject.h index 4e8ae8ab27..77f7b3e0d6 100644 --- a/src/libtiled/mapobject.h +++ b/src/libtiled/mapobject.h @@ -99,6 +99,7 @@ class TILEDSHARED_EXPORT MapObject : public Object Polygon, Polyline, Ellipse, + Capsule, Text, Point, }; diff --git a/src/libtiled/mapreader.cpp b/src/libtiled/mapreader.cpp index 5c6e646e42..ee58d5708a 100644 --- a/src/libtiled/mapreader.cpp +++ b/src/libtiled/mapreader.cpp @@ -1252,6 +1252,10 @@ std::unique_ptr MapReaderPrivate::readObject() xml.skipCurrentElement(); object->setShape(MapObject::Ellipse); object->setPropertyChanged(MapObject::ShapeProperty); + } else if (xml.name() == QLatin1String("capsule")) { + xml.skipCurrentElement(); + object->setShape(MapObject::Capsule); + object->setPropertyChanged(MapObject::ShapeProperty); } else if (xml.name() == QLatin1String("text")) { object->setTextData(readObjectText()); object->setShape(MapObject::Text); diff --git a/src/libtiled/maptovariantconverter.cpp b/src/libtiled/maptovariantconverter.cpp index ac1dc93ff6..603a6639a2 100644 --- a/src/libtiled/maptovariantconverter.cpp +++ b/src/libtiled/maptovariantconverter.cpp @@ -622,6 +622,10 @@ QVariant MapToVariantConverter::toVariant(const MapObject &object) const if (notTemplateInstance || object.propertyChanged(MapObject::ShapeProperty)) objectVariant[QStringLiteral("ellipse")] = true; break; + case MapObject::Capsule: + if (notTemplateInstance || object.propertyChanged(MapObject::ShapeProperty)) + objectVariant[QStringLiteral("capsule")] = true; + break; case MapObject::Text: if (notTemplateInstance || (object.propertyChanged(MapObject::TextProperty) || object.propertyChanged(MapObject::TextFontProperty) || diff --git a/src/libtiled/mapwriter.cpp b/src/libtiled/mapwriter.cpp index fc41107538..d90e00f85c 100644 --- a/src/libtiled/mapwriter.cpp +++ b/src/libtiled/mapwriter.cpp @@ -793,6 +793,10 @@ void MapWriterPrivate::writeObject(QXmlStreamWriter &w, if (shouldWrite(true, isTemplateInstance, mapObject.propertyChanged(MapObject::ShapeProperty))) w.writeEmptyElement(QLatin1String("ellipse")); break; + case MapObject::Capsule: + if (shouldWrite(true, isTemplateInstance, mapObject.propertyChanged(MapObject::ShapeProperty))) + w.writeEmptyElement(QLatin1String("capsule")); + break; case MapObject::Text: { if (shouldWrite(true, isTemplateInstance, mapObject.propertyChanged(MapObject::TextProperty) || diff --git a/src/libtiled/orthogonalrenderer.cpp b/src/libtiled/orthogonalrenderer.cpp index e8096d1bcd..e5fd9360a1 100644 --- a/src/libtiled/orthogonalrenderer.cpp +++ b/src/libtiled/orthogonalrenderer.cpp @@ -77,6 +77,7 @@ QRectF OrthogonalRenderer::boundingRect(const MapObject *object) const switch (object->shape()) { case MapObject::Ellipse: + case MapObject::Capsule: case MapObject::Rectangle: if (bounds.isNull()) { boundingRect = bounds.adjusted(-10 - extraSpace, @@ -172,6 +173,15 @@ QPainterPath OrthogonalRenderer::shape(const MapObject *object) const path.addEllipse(bounds); break; } + case MapObject::Capsule: { + const qreal rad = std::min(std::abs(bounds.height()), + std::abs(bounds.width())) / 2; + if (rad == 0.) + path.addEllipse(bounds.topLeft(), 10, 10); + else + path.addRoundedRect(bounds, rad, rad, Qt::SizeMode::AbsoluteSize); + break; + } case MapObject::Point: path = pointShape(object->position()); break; @@ -203,6 +213,7 @@ QPainterPath OrthogonalRenderer::interactionShape(const MapObject *object) const case MapObject::Rectangle: case MapObject::Polygon: case MapObject::Ellipse: + case MapObject::Capsule: case MapObject::Text: path = shape(object); break; @@ -394,7 +405,7 @@ void OrthogonalRenderer::drawMapObject(QPainter *painter, // CoreGraphics when drawing the path requested by the // QCoreGraphicsPaintEngine. Draw them as rectangle instead. MapObject::Shape shape = object->shape(); - if (shape == MapObject::Ellipse && + if ((shape == MapObject::Ellipse || shape == MapObject::Capsule) && ((bounds.width() == qreal(0)) ^ (bounds.height() == qreal(0)))) { shape = MapObject::Rectangle; } @@ -458,6 +469,23 @@ void OrthogonalRenderer::drawMapObject(QPainter *painter, break; } + case MapObject::Capsule: { + if (bounds.isNull()) + bounds = QRectF(QPointF(-10, -10), QSizeF(20, 20)); + + const qreal rad = std::min(std::abs(bounds.height()), + std::abs(bounds.width())) / 2; + + // Draw the shadow + painter->setPen(shadowPen); + painter->drawRoundedRect(bounds.translated(shadowOffset), rad, rad); + + painter->setPen(linePen); + painter->setBrush(fillBrush); + painter->drawRoundedRect(bounds, rad, rad); + break; + } + case MapObject::Text: { const auto& textData = object->textData(); painter->setFont(textData.font); diff --git a/src/libtiled/varianttomapconverter.cpp b/src/libtiled/varianttomapconverter.cpp index 0cff37447a..4e83959751 100644 --- a/src/libtiled/varianttomapconverter.cpp +++ b/src/libtiled/varianttomapconverter.cpp @@ -806,6 +806,7 @@ std::unique_ptr VariantToMapConverter::toMapObject(const QVariantMap const QVariant polylineVariant = variantMap[QStringLiteral("polyline")]; const QVariant polygonVariant = variantMap[QStringLiteral("polygon")]; const QVariant ellipseVariant = variantMap[QStringLiteral("ellipse")]; + const QVariant capsuleVariant = variantMap[QStringLiteral("capsule")]; const QVariant pointVariant = variantMap[QStringLiteral("point")]; const QVariant textVariant = variantMap[QStringLiteral("text")]; @@ -823,6 +824,10 @@ std::unique_ptr VariantToMapConverter::toMapObject(const QVariantMap object->setShape(MapObject::Ellipse); object->setPropertyChanged(MapObject::ShapeProperty); } + if (capsuleVariant.toBool()) { + object->setShape(MapObject::Capsule); + object->setPropertyChanged(MapObject::ShapeProperty); + } if (pointVariant.toBool()) { object->setShape(MapObject::Point); object->setPropertyChanged(MapObject::ShapeProperty); diff --git a/src/plugins/lua/luaplugin.cpp b/src/plugins/lua/luaplugin.cpp index 64db6cce8a..c088302b66 100644 --- a/src/plugins/lua/luaplugin.cpp +++ b/src/plugins/lua/luaplugin.cpp @@ -708,6 +708,8 @@ static const char *toString(MapObject::Shape shape) return "polyline"; case MapObject::Ellipse: return "ellipse"; + case MapObject::Capsule: + return "capsule"; case MapObject::Text: return "text"; case MapObject::Point: @@ -739,6 +741,7 @@ void LuaWriter::writeMapObject(const Tiled::MapObject *mapObject) switch (mapObject->shape()) { case MapObject::Rectangle: case MapObject::Ellipse: + case MapObject::Capsule: case MapObject::Point: break; case MapObject::Polygon: diff --git a/src/plugins/python/pythonbind.cpp b/src/plugins/python/pythonbind.cpp index 18d5f5cb3d..52313f23f0 100644 --- a/src/plugins/python/pythonbind.cpp +++ b/src/plugins/python/pythonbind.cpp @@ -7675,6 +7675,10 @@ inittiled_Tiled(void) // Tiled::MapObject::Ellipse tmp_value = PyLong_FromLong(Tiled::MapObject::Ellipse); PyDict_SetItemString((PyObject*) PyTiledMapObject_Type.tp_dict, "Ellipse", tmp_value); + Py_DECREF(tmp_value); + // Tiled::MapObject::Capsule + tmp_value = PyLong_FromLong(Tiled::MapObject::Capsule); + PyDict_SetItemString((PyObject*) PyTiledMapObject_Type.tp_dict, "Capsule", tmp_value); Py_DECREF(tmp_value); // Tiled::MapObject::Text tmp_value = PyLong_FromLong(Tiled::MapObject::Text); diff --git a/src/tiled/createcapsuleobjecttool.cpp b/src/tiled/createcapsuleobjecttool.cpp new file mode 100644 index 0000000000..da012dfe5d --- /dev/null +++ b/src/tiled/createcapsuleobjecttool.cpp @@ -0,0 +1,58 @@ +/* + * createcapsuleobjecttool.cpp + * Copyright 2025, Jocelyn + * + * 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 . + */ + +#include "createcapsuleobjecttool.h" + +#include "mapobject.h" +#include "utils.h" + +using namespace Tiled; + +CreateCapsuleObjectTool::CreateCapsuleObjectTool(QObject *parent) + : CreateScalableObjectTool("CreateCapsuleObjectTool", + parent) +{ + QIcon icon(QLatin1String(":images/24/insert-capsule.png")); + icon.addFile(QLatin1String(":images/48/insert-capsule.png")); + setIcon(icon); + setShortcut(Qt::SHIFT + Qt::Key_C); + Utils::setThemeIcon(this, "insert-capsule"); + languageChangedImpl(); +} + +void CreateCapsuleObjectTool::languageChanged() +{ + CreateScalableObjectTool::languageChanged(); + languageChangedImpl(); +} + +void CreateCapsuleObjectTool::languageChangedImpl() +{ + setName(tr("Insert Capsule")); +} + +MapObject *CreateCapsuleObjectTool::createNewMapObject() +{ + auto newMapObject = new MapObject; + newMapObject->setShape(MapObject::Capsule); + return newMapObject; +} + +#include "moc_createcapsuleobjecttool.cpp" diff --git a/src/tiled/createcapsuleobjecttool.h b/src/tiled/createcapsuleobjecttool.h new file mode 100644 index 0000000000..b71834f64d --- /dev/null +++ b/src/tiled/createcapsuleobjecttool.h @@ -0,0 +1,43 @@ +/* + * createcapsulebjecttool.h + * Copyright 2025, Jocelyn + * + * 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 . + */ + +#pragma once + +#include "createscalableobjecttool.h" + +namespace Tiled { + +class CreateCapsuleObjectTool : public CreateScalableObjectTool +{ + Q_OBJECT + +public: + CreateCapsuleObjectTool(QObject *parent); + + void languageChanged() override; + +protected: + MapObject *createNewMapObject() override; + +private: + void languageChangedImpl(); +}; + +} // namespace Tiled diff --git a/src/tiled/editablemapobject.h b/src/tiled/editablemapobject.h index a43b971f1f..001f28b12a 100644 --- a/src/tiled/editablemapobject.h +++ b/src/tiled/editablemapobject.h @@ -86,6 +86,7 @@ class EditableMapObject : public EditableObject Polygon, Polyline, Ellipse, + Capsule, Text, Point, }; diff --git a/src/tiled/libtilededitor.qbs b/src/tiled/libtilededitor.qbs index 1733a758da..078531ca3b 100644 --- a/src/tiled/libtilededitor.qbs +++ b/src/tiled/libtilededitor.qbs @@ -178,6 +178,8 @@ DynamicLibrary { "commandsedit.ui", "consoledock.cpp", "consoledock.h", + "createcapsuleobjecttool.cpp", + "createcapsuleobjecttool.h", "createellipseobjecttool.cpp", "createellipseobjecttool.h", "createobjecttool.cpp", diff --git a/src/tiled/mapeditor.cpp b/src/tiled/mapeditor.cpp index c99388bace..80c529c6cd 100644 --- a/src/tiled/mapeditor.cpp +++ b/src/tiled/mapeditor.cpp @@ -23,6 +23,7 @@ #include "addremovetileset.h" #include "bucketfilltool.h" #include "changeselectedarea.h" +#include "createcapsuleobjecttool.h" #include "createellipseobjecttool.h" #include "createobjecttool.h" #include "createpointobjecttool.h" @@ -179,6 +180,7 @@ MapEditor::MapEditor(QObject *parent) CreateObjectTool *rectangleObjectsTool = new CreateRectangleObjectTool(this); CreateObjectTool *pointObjectsTool = new CreatePointObjectTool(this); CreateObjectTool *ellipseObjectsTool = new CreateEllipseObjectTool(this); + CreateObjectTool *capsuleObjectsTool = new CreateCapsuleObjectTool(this); CreateObjectTool *polygonObjectsTool = new CreatePolygonObjectTool(this); CreateObjectTool *textObjectsTool = new CreateTextObjectTool(this); @@ -197,6 +199,7 @@ MapEditor::MapEditor(QObject *parent) mToolsToolBar->addAction(mToolManager->registerTool(rectangleObjectsTool)); mToolsToolBar->addAction(mToolManager->registerTool(pointObjectsTool)); mToolsToolBar->addAction(mToolManager->registerTool(ellipseObjectsTool)); + mToolsToolBar->addAction(mToolManager->registerTool(capsuleObjectsTool)); mToolsToolBar->addAction(mToolManager->registerTool(polygonObjectsTool)); mToolsToolBar->addAction(mToolManager->registerTool(tileObjectsTool)); mToolsToolBar->addAction(mToolManager->registerTool(templatesTool)); diff --git a/src/tiled/mapobjectmodel.cpp b/src/tiled/mapobjectmodel.cpp index 26a644d403..4d06a54ba8 100644 --- a/src/tiled/mapobjectmodel.cpp +++ b/src/tiled/mapobjectmodel.cpp @@ -43,6 +43,7 @@ ObjectIconManager::ObjectIconManager() , mPolygonIcon(QLatin1String(":images/24/object-polygon.png")) , mPolylineIcon(QLatin1String(":images/24/object-polyline.png")) , mEllipseIcon(QLatin1String(":images/24/object-ellipse.png")) + , mCapsuleIcon(QLatin1String(":images/24/object-capsule.png")) , mTextIcon(QLatin1String(":images/24/object-text.png")) , mPointIcon(QLatin1String(":images/24/object-point.png")) {} @@ -64,6 +65,8 @@ const QIcon &ObjectIconManager::iconForObject(const MapObject &object) const return mPolylineIcon; case MapObject::Ellipse: return mEllipseIcon; + case MapObject::Capsule: + return mCapsuleIcon; case MapObject::Text: return mTextIcon; case MapObject::Point: diff --git a/src/tiled/mapobjectmodel.h b/src/tiled/mapobjectmodel.h index aebbc64e47..9abe7fa2c5 100644 --- a/src/tiled/mapobjectmodel.h +++ b/src/tiled/mapobjectmodel.h @@ -52,6 +52,7 @@ class ObjectIconManager const QIcon mPolygonIcon; const QIcon mPolylineIcon; const QIcon mEllipseIcon; + const QIcon mCapsuleIcon; const QIcon mTextIcon; const QIcon mPointIcon; }; diff --git a/src/tiled/objectselectiontool.cpp b/src/tiled/objectselectiontool.cpp index 2c6dd9187e..e5d4d7c5e6 100644 --- a/src/tiled/objectselectiontool.cpp +++ b/src/tiled/objectselectiontool.cpp @@ -828,6 +828,7 @@ static QRectF pixelBounds(const MapObject *object) switch (object->shape()) { case MapObject::Ellipse: + case MapObject::Capsule: case MapObject::Rectangle: case MapObject::Point: { QRectF bounds(object->bounds()); @@ -864,6 +865,7 @@ static bool canResizeAbsolute(const MapObject *object) switch (object->shape()) { case MapObject::Rectangle: case MapObject::Ellipse: + case MapObject::Capsule: case MapObject::Text: return true; case MapObject::Point: @@ -914,6 +916,7 @@ static QRectF objectBounds(const MapObject *object, } else { switch (object->shape()) { case MapObject::Ellipse: + case MapObject::Capsule: case MapObject::Rectangle: { QRectF bounds(object->bounds()); align(bounds, object->alignment()); diff --git a/src/tiled/resources/images/24/insert-capsule.png b/src/tiled/resources/images/24/insert-capsule.png new file mode 100644 index 0000000000..c58b057952 Binary files /dev/null and b/src/tiled/resources/images/24/insert-capsule.png differ diff --git a/src/tiled/resources/images/24/object-capsule.png b/src/tiled/resources/images/24/object-capsule.png new file mode 100644 index 0000000000..84f08092b8 Binary files /dev/null and b/src/tiled/resources/images/24/object-capsule.png differ diff --git a/src/tiled/resources/images/48/insert-capsule.png b/src/tiled/resources/images/48/insert-capsule.png new file mode 100644 index 0000000000..6a1550f1d9 Binary files /dev/null and b/src/tiled/resources/images/48/insert-capsule.png differ diff --git a/src/tiled/resources/images/parts/icons.tmx b/src/tiled/resources/images/parts/icons.tmx index 484d88ca2a..b425430e96 100644 --- a/src/tiled/resources/images/parts/icons.tmx +++ b/src/tiled/resources/images/parts/icons.tmx @@ -1,36 +1,41 @@ - + - + - + eJxjZGBgAAAACAAC - + - + - + - + + + + + + - + diff --git a/src/tiled/tilecollisiondock.cpp b/src/tiled/tilecollisiondock.cpp index e5454d90b8..b9ea933371 100644 --- a/src/tiled/tilecollisiondock.cpp +++ b/src/tiled/tilecollisiondock.cpp @@ -23,6 +23,7 @@ #include "actionmanager.h" #include "addremovemapobject.h" #include "changetileobjectgroup.h" +#include "createcapsuleobjecttool.h" #include "createellipseobjecttool.h" #include "createobjecttool.h" #include "createpointobjecttool.h" @@ -92,6 +93,7 @@ TileCollisionDock::TileCollisionDock(QWidget *parent) CreateObjectTool *rectangleObjectsTool = new CreateRectangleObjectTool(this); CreateObjectTool *pointObjectsTool = new CreatePointObjectTool(this); CreateObjectTool *ellipseObjectsTool = new CreateEllipseObjectTool(this); + CreateObjectTool *capsuleObjectsTool = new CreateCapsuleObjectTool(this); CreateObjectTool *polygonObjectsTool = new CreatePolygonObjectTool(this); CreateObjectTool *templatesTool = new CreateTemplateTool(this); @@ -116,6 +118,7 @@ TileCollisionDock::TileCollisionDock(QWidget *parent) toolsToolBar->addAction(mToolManager->registerTool(rectangleObjectsTool)); toolsToolBar->addAction(mToolManager->registerTool(pointObjectsTool)); toolsToolBar->addAction(mToolManager->registerTool(ellipseObjectsTool)); + toolsToolBar->addAction(mToolManager->registerTool(capsuleObjectsTool)); toolsToolBar->addAction(mToolManager->registerTool(polygonObjectsTool)); toolsToolBar->addAction(mToolManager->registerTool(templatesTool)); toolsToolBar->addSeparator();