From d57bd6b0c00d629ec162aadb018edde9d69151b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thorbj=C3=B8rn=20Lindeijer?= Date: Thu, 4 Jul 2013 17:51:05 +0200 Subject: [PATCH] Introduced object group drawing order attribute This attribute allows specifying per object group whether its objects should be drawn top down (from top to bottom) or in index order (which enables manual ordering). This change also fixes an issue where new objects could be invisible during placement due to being drawn below other layers. --- src/libtiled/mapreader.cpp | 11 ++++ src/libtiled/mapwriter.cpp | 3 + src/libtiled/objectgroup.cpp | 35 ++++++++++- src/libtiled/objectgroup.h | 74 ++++++++++++++++++++--- src/tiled/abstractobjecttool.cpp | 30 ++++----- src/tiled/changeobjectgroupproperties.cpp | 15 +++-- src/tiled/changeobjectgroupproperties.h | 10 +-- src/tiled/createobjecttool.cpp | 2 + src/tiled/mapdocument.h | 2 +- src/tiled/mapobjectitem.cpp | 5 +- src/tiled/mapscene.cpp | 29 ++++++++- src/tiled/mapscene.h | 1 + src/tiled/objectselectiontool.cpp | 8 ++- src/tiled/propertybrowser.cpp | 41 +++++++++++-- src/tiled/propertybrowser.h | 2 + src/tiled/raiselowerhelper.cpp | 37 +++++++----- src/tiled/raiselowerhelper.h | 6 ++ 17 files changed, 245 insertions(+), 66 deletions(-) diff --git a/src/libtiled/mapreader.cpp b/src/libtiled/mapreader.cpp index 21c10dfb03..691ea99d3c 100644 --- a/src/libtiled/mapreader.cpp +++ b/src/libtiled/mapreader.cpp @@ -681,6 +681,17 @@ ObjectGroup *MapReaderPrivate::readObjectGroup() if (!color.isEmpty()) objectGroup->setColor(color); + if (atts.hasAttribute(QLatin1String("draworder"))) { + QString value = atts.value(QLatin1String("draworder")).toString(); + ObjectGroup::DrawOrder drawOrder = drawOrderFromString(value); + if (drawOrder == ObjectGroup::UnknownOrder) { + delete objectGroup; + xml.raiseError(tr("Invalid draw order: %1").arg(value)); + return 0; + } + objectGroup->setDrawOrder(drawOrder); + } + while (xml.readNextStartElement()) { if (xml.name() == QLatin1String("object")) objectGroup->addObject(readObject()); diff --git a/src/libtiled/mapwriter.cpp b/src/libtiled/mapwriter.cpp index f2a5c2077f..83078393b8 100644 --- a/src/libtiled/mapwriter.cpp +++ b/src/libtiled/mapwriter.cpp @@ -448,6 +448,9 @@ void MapWriterPrivate::writeObjectGroup(QXmlStreamWriter &w, w.writeAttribute(QLatin1String("color"), objectGroup->color().name()); + w.writeAttribute(QLatin1String("draworder"), + drawOrderToString(objectGroup->drawOrder())); + writeLayerAttributes(w, objectGroup); writeProperties(w, objectGroup->properties()); diff --git a/src/libtiled/objectgroup.cpp b/src/libtiled/objectgroup.cpp index 02703df56a..182db14b96 100644 --- a/src/libtiled/objectgroup.cpp +++ b/src/libtiled/objectgroup.cpp @@ -40,12 +40,14 @@ using namespace Tiled; ObjectGroup::ObjectGroup() : Layer(ObjectGroupType, QString(), 0, 0, 0, 0) + , mDrawOrder(TopDownOrder) { } ObjectGroup::ObjectGroup(const QString &name, int x, int y, int width, int height) : Layer(ObjectGroupType, name, x, y, width, height) + , mDrawOrder(TopDownOrder) { } @@ -88,9 +90,9 @@ void ObjectGroup::moveObjects(int from, int to, int count) Q_ASSERT(count >= 0); Q_ASSERT(to <= from || to >= from + count); - // Nothing to be done when 'to' is the start of the end of the range, or + // Nothing to be done when 'to' is the start or the end of the range, or // when the number of objects to be moved is 0. - if (count == 0 || to == from || to == from + count) + if (to == from || to == from + count || count == 0) return; const QList movingObjects = mObjects.mid(from, count); @@ -233,3 +235,32 @@ ObjectGroup *ObjectGroup::initializeClone(ObjectGroup *clone) const clone->setColor(mColor); return clone; } + + +QString Tiled::drawOrderToString(ObjectGroup::DrawOrder drawOrder) +{ + switch (drawOrder) { + default: + case ObjectGroup::UnknownOrder: + return QLatin1String("unknown"); + break; + case ObjectGroup::TopDownOrder: + return QLatin1String("topdown"); + break; + case ObjectGroup::IndexOrder: + return QLatin1String("index"); + break; + } +} + +ObjectGroup::DrawOrder Tiled::drawOrderFromString(const QString &string) +{ + ObjectGroup::DrawOrder drawOrder = ObjectGroup::UnknownOrder; + + if (string == QLatin1String("topdown")) + drawOrder = ObjectGroup::TopDownOrder; + else if (string == QLatin1String("index")) + drawOrder = ObjectGroup::IndexOrder; + + return drawOrder; +} diff --git a/src/libtiled/objectgroup.h b/src/libtiled/objectgroup.h index e62931dfd8..b46e2150f5 100644 --- a/src/libtiled/objectgroup.h +++ b/src/libtiled/objectgroup.h @@ -49,6 +49,18 @@ class MapObject; class TILEDSHARED_EXPORT ObjectGroup : public Layer { public: + /** + * Objects within an object group can either be drawn top down (sorted + * by their y-coordinate) or by index (manual stacking order). + * + * The default is top down. + */ + enum DrawOrder { + UnknownOrder = -1, + TopDownOrder, + IndexOrder + }; + /** * Default constructor. */ @@ -165,16 +177,11 @@ class TILEDSHARED_EXPORT ObjectGroup : public Layer bool canMergeWith(Layer *other) const; Layer *mergedWith(Layer *other) const; - /** - * Returns the color of the object group, or an invalid color if no color - * is set. - */ - const QColor &color() const { return mColor; } + const QColor &color() const; + void setColor(const QColor &color); - /** - * Sets the display color of the object group. - */ - void setColor(const QColor &color) { mColor = color; } + DrawOrder drawOrder() const; + void setDrawOrder(DrawOrder drawOrder); Layer *clone() const; @@ -184,8 +191,57 @@ class TILEDSHARED_EXPORT ObjectGroup : public Layer private: QList mObjects; QColor mColor; + DrawOrder mDrawOrder; }; + +/** + * Returns the color of the object group, or an invalid color if no color + * is set. + */ +inline const QColor &ObjectGroup::color() const +{ return mColor; } + +/** + * Sets the display color of the object group. + */ +inline void ObjectGroup::setColor(const QColor &color) +{ mColor = color; } + +/** + * Returns the draw order for the objects in this group. + * + * \sa ObjectGroup::DrawOrder + */ +inline ObjectGroup::DrawOrder ObjectGroup::drawOrder() const +{ return mDrawOrder; } + +/** + * Sets the draw order for the objects in this group. + * + * \sa ObjectGroup::DrawOrder + */ +inline void ObjectGroup::setDrawOrder(DrawOrder drawOrder) +{ mDrawOrder = drawOrder; } + + +/** + * Helper function that converts a drawing order to its string value. Useful + * for map writers. + * + * @return The draw order as a lowercase string. + */ +TILEDSHARED_EXPORT QString drawOrderToString(ObjectGroup::DrawOrder); + +/** + * Helper function that converts a string to a drawing order enumerator. + * Useful for map readers. + * + * @return The draw order matching the given string, or + * ObjectGroup::UnknownOrder if the string is unrecognized. + */ +TILEDSHARED_EXPORT ObjectGroup::DrawOrder drawOrderFromString(const QString &); + } // namespace Tiled Q_DECLARE_METATYPE(Tiled::ObjectGroup*) diff --git a/src/tiled/abstractobjecttool.cpp b/src/tiled/abstractobjecttool.cpp index 13ba71ce5a..dfd33a426e 100644 --- a/src/tiled/abstractobjecttool.cpp +++ b/src/tiled/abstractobjecttool.cpp @@ -162,12 +162,7 @@ void AbstractObjectTool::showContextMenu(MapObjectItem *clickedObjectItem, return; const QList &selectedObjects = mapDocument()->selectedObjects(); - - QList objectGroups; - foreach (Layer *layer, mapDocument()->map()->layers()) { - if (ObjectGroup *objectGroup = layer->asObjectGroup()) - objectGroups.append(objectGroup); - } + const QList objectGroups = mapDocument()->map()->objectGroups(); MapDocumentActionHandler *handler = MapDocumentActionHandler::instance(); @@ -176,20 +171,17 @@ void AbstractObjectTool::showContextMenu(MapObjectItem *clickedObjectItem, menu.addAction(handler->actionRemoveObjects()); menu.addSeparator(); - QAction *horizontalAction = menu.addAction(tr("Flip Horizontally")); - QAction *verticalAction = menu.addAction(tr("Flip Vertically")); - connect(horizontalAction, SIGNAL(triggered()), SLOT(flipHorizontally())); - connect(verticalAction, SIGNAL(triggered()), SLOT(flipVertically())); + menu.addAction(tr("Flip Horizontally"), this, SLOT(flipHorizontally()), QKeySequence(tr("X"))); + menu.addAction(tr("Flip Vertically"), this, SLOT(flipVertically()), QKeySequence(tr("Y"))); - menu.addSeparator(); - QAction *raiseAction = menu.addAction(tr("Raise Object")); - QAction *lowerAction = menu.addAction(tr("Lower Object")); - QAction *raiseToTopAction = menu.addAction(tr("Raise Object to Top")); - QAction *lowerToBottomAction = menu.addAction(tr("Lower Object to Bottom")); - connect(raiseAction, SIGNAL(triggered()), SLOT(raise())); - connect(lowerAction, SIGNAL(triggered()), SLOT(lower())); - connect(raiseToTopAction, SIGNAL(triggered()), SLOT(raiseToTop())); - connect(lowerToBottomAction, SIGNAL(triggered()), SLOT(lowerToBottom())); + ObjectGroup *objectGroup = RaiseLowerHelper::sameObjectGroup(selection); + if (objectGroup && objectGroup->drawOrder() == ObjectGroup::IndexOrder) { + menu.addSeparator(); + menu.addAction(tr("Raise Object"), this, SLOT(raise()), QKeySequence(tr("PgUp"))); + menu.addAction(tr("Lower Object"), this, SLOT(lower()), QKeySequence(tr("PgDown"))); + menu.addAction(tr("Raise Object to Top"), this, SLOT(raiseToTop()), QKeySequence(tr("Home"))); + menu.addAction(tr("Lower Object to Bottom"), this, SLOT(lowerToBottom()), QKeySequence(tr("End"))); + } if (objectGroups.size() > 1) { menu.addSeparator(); diff --git a/src/tiled/changeobjectgroupproperties.cpp b/src/tiled/changeobjectgroupproperties.cpp index 7c4093e418..ee43e528d0 100644 --- a/src/tiled/changeobjectgroupproperties.cpp +++ b/src/tiled/changeobjectgroupproperties.cpp @@ -31,29 +31,32 @@ using namespace Tiled; using namespace Tiled::Internal; ChangeObjectGroupProperties::ChangeObjectGroupProperties( - MapDocument *mapDocument, - ObjectGroup *objectGroup, - const QColor &color) + MapDocument *mapDocument, + ObjectGroup *objectGroup, + const QColor &newColor, + ObjectGroup::DrawOrder newDrawOrder) : QUndoCommand( QCoreApplication::translate( "Undo Commands", "Change Object Layer Properties")) , mMapDocument(mapDocument) , mObjectGroup(objectGroup) , mUndoColor(objectGroup->color()) - , mRedoColor(color) + , mRedoColor(newColor) + , mUndoDrawOrder(objectGroup->drawOrder()) + , mRedoDrawOrder(newDrawOrder) { } void ChangeObjectGroupProperties::redo() { mObjectGroup->setColor(mRedoColor); - mMapDocument->mapObjectModel()->emitObjectsChanged(mObjectGroup->objects()); + mObjectGroup->setDrawOrder(mRedoDrawOrder); mMapDocument->emitObjectGroupChanged(mObjectGroup); } void ChangeObjectGroupProperties::undo() { mObjectGroup->setColor(mUndoColor); - mMapDocument->mapObjectModel()->emitObjectsChanged(mObjectGroup->objects()); + mObjectGroup->setDrawOrder(mUndoDrawOrder); mMapDocument->emitObjectGroupChanged(mObjectGroup); } diff --git a/src/tiled/changeobjectgroupproperties.h b/src/tiled/changeobjectgroupproperties.h index d76ee71de1..78ddb63aa2 100644 --- a/src/tiled/changeobjectgroupproperties.h +++ b/src/tiled/changeobjectgroupproperties.h @@ -22,13 +22,12 @@ #ifndef CHANGEOBJECTGROUPPROPERTIES_H #define CHANGEOBJECTGROUPPROPERTIES_H +#include "objectgroup.h" + #include #include namespace Tiled { - -class ObjectGroup; - namespace Internal { class MapDocument; @@ -45,7 +44,8 @@ class ChangeObjectGroupProperties : public QUndoCommand */ ChangeObjectGroupProperties(MapDocument *mapDocument, ObjectGroup *objectGroup, - const QColor &newColor); + const QColor &newColor, + ObjectGroup::DrawOrder newDrawOrder); void undo(); void redo(); @@ -55,6 +55,8 @@ class ChangeObjectGroupProperties : public QUndoCommand ObjectGroup *mObjectGroup; const QColor mUndoColor; const QColor mRedoColor; + ObjectGroup::DrawOrder mUndoDrawOrder; + ObjectGroup::DrawOrder mRedoDrawOrder; }; } // namespace Internal diff --git a/src/tiled/createobjecttool.cpp b/src/tiled/createobjecttool.cpp index e33946ab5b..c605808b89 100644 --- a/src/tiled/createobjecttool.cpp +++ b/src/tiled/createobjecttool.cpp @@ -162,6 +162,7 @@ void CreateObjectTool::mouseMoved(const QPointF &pos, mNewMapObjectItem->mapObject()->setPosition(tileCoords); mNewMapObjectItem->syncWithMapObject(); + mNewMapObjectItem->setZValue(10000); // sync may change it break; } case CreatePolygon: @@ -337,6 +338,7 @@ void CreateObjectTool::startNewMapObject(const QPointF &pos, objectGroup->addObject(newMapObject); mNewMapObjectItem = new MapObjectItem(newMapObject, mapDocument()); + mNewMapObjectItem->setZValue(10000); // same as the BrushItem mapScene()->addItem(mNewMapObjectItem); } diff --git a/src/tiled/mapdocument.h b/src/tiled/mapdocument.h index 22059f74ba..5849037fd3 100644 --- a/src/tiled/mapdocument.h +++ b/src/tiled/mapdocument.h @@ -410,7 +410,7 @@ inline void MapDocument::emitTileTerrainChanged(const QList &tiles) /** * Emits the objectGroupChanged signal, should be called when changing the - * color of an object group. + * color or drawing order of an object group. */ inline void MapDocument::emitObjectGroupChanged(ObjectGroup *objectGroup) { diff --git a/src/tiled/mapobjectitem.cpp b/src/tiled/mapobjectitem.cpp index a95db58ec1..2221343acd 100644 --- a/src/tiled/mapobjectitem.cpp +++ b/src/tiled/mapobjectitem.cpp @@ -225,9 +225,12 @@ void MapObjectItem::syncWithMapObject() bounds.translate(-pixelPos); setPos(pixelPos); -// setZValue(pixelPos.y()); setRotation(mObject->rotation()); + if (ObjectGroup *objectGroup = mObject->objectGroup()) + if (objectGroup->drawOrder() == ObjectGroup::TopDownOrder) + setZValue(pixelPos.y()); + mSyncing = true; if (mBoundingRect != bounds) { diff --git a/src/tiled/mapscene.cpp b/src/tiled/mapscene.cpp index 504321ae26..1a6e52aec2 100644 --- a/src/tiled/mapscene.cpp +++ b/src/tiled/mapscene.cpp @@ -120,6 +120,8 @@ void MapScene::setMapDocument(MapDocument *mapDocument) this, SLOT(layerRemoved(int))); connect(mMapDocument, SIGNAL(layerChanged(int)), this, SLOT(layerChanged(int))); + connect(mMapDocument, SIGNAL(objectGroupChanged(ObjectGroup*)), + this, SLOT(objectGroupChanged(ObjectGroup*))); connect(mMapDocument, SIGNAL(imageLayerChanged(ImageLayer*)), this, SLOT(imageLayerChanged(ImageLayer*))); connect(mMapDocument, SIGNAL(currentLayerIndexChanged(int)), @@ -203,12 +205,17 @@ QGraphicsItem *MapScene::createLayerItem(Layer *layer) if (TileLayer *tl = layer->asTileLayer()) { layerItem = new TileLayerItem(tl, mMapDocument->renderer()); } else if (ObjectGroup *og = layer->asObjectGroup()) { + const ObjectGroup::DrawOrder drawOrder = og->drawOrder(); ObjectGroupItem *ogItem = new ObjectGroupItem(og); int objectIndex = 0; foreach (MapObject *object, og->objects()) { MapObjectItem *item = new MapObjectItem(object, mMapDocument, ogItem); - item->setZValue(objectIndex); + if (drawOrder == ObjectGroup::TopDownOrder) + item->setZValue(item->y()); + else + item->setZValue(objectIndex); + mObjectItems.insert(object, item); ++objectIndex; } @@ -367,6 +374,16 @@ void MapScene::layerChanged(int index) layerItem->setOpacity(layer->opacity() * multiplier); } +/** + * When an object group has changed it may mean its color or drawing order + * changed, which affects all its objects. + */ +void MapScene::objectGroupChanged(ObjectGroup *objectGroup) +{ + objectsChanged(objectGroup->objects()); + objectsIndexChanged(objectGroup, 0, objectGroup->objectCount() - 1); +} + /** * When an image layer has changed, it may change size and it may look * differently. @@ -399,11 +416,16 @@ void MapScene::objectsInserted(ObjectGroup *objectGroup, int first, int last) Q_ASSERT(ogItem); + const ObjectGroup::DrawOrder drawOrder = objectGroup->drawOrder(); + for (int i = first; i <= last; ++i) { MapObject *object = objectGroup->objectAt(i); MapObjectItem *item = new MapObjectItem(object, mMapDocument, ogItem); - item->setZValue(i); + if (drawOrder == ObjectGroup::TopDownOrder) + item->setZValue(item->y()); + else + item->setZValue(i); mObjectItems.insert(object, item); } @@ -443,6 +465,9 @@ void MapScene::objectsChanged(const QList &objects) void MapScene::objectsIndexChanged(ObjectGroup *objectGroup, int first, int last) { + if (objectGroup->drawOrder() != ObjectGroup::IndexOrder) + return; + for (int i = first; i <= last; ++i) { MapObjectItem *item = itemForObject(objectGroup->objectAt(i)); Q_ASSERT(item); diff --git a/src/tiled/mapscene.h b/src/tiled/mapscene.h index 353f4923b7..4483635853 100644 --- a/src/tiled/mapscene.h +++ b/src/tiled/mapscene.h @@ -161,6 +161,7 @@ private slots: void layerRemoved(int index); void layerChanged(int index); + void objectGroupChanged(ObjectGroup *objectGroup); void imageLayerChanged(ImageLayer *imageLayer); void objectsInserted(ObjectGroup *objectGroup, int first, int last); diff --git a/src/tiled/objectselectiontool.cpp b/src/tiled/objectselectiontool.cpp index 4a73fdcc51..b6613a2a49 100644 --- a/src/tiled/objectselectiontool.cpp +++ b/src/tiled/objectselectiontool.cpp @@ -566,8 +566,12 @@ void ObjectSelectionTool::updateMovingItems(const QPointF &pos, const QPointF newPixelPos = mOldObjectItemPositions.at(i) + diff; const QPointF newPos = renderer->pixelToTileCoords(newPixelPos); objectItem->setPos(newPixelPos); -// objectItem->setZValue(newPixelPos.y()); objectItem->mapObject()->setPosition(newPos); + + ObjectGroup *objectGroup = objectItem->mapObject()->objectGroup(); + if (objectGroup->drawOrder() == ObjectGroup::TopDownOrder) + objectItem->setZValue(newPixelPos.y()); + ++i; } } @@ -646,9 +650,9 @@ void ObjectSelectionTool::updateRotatingItems(const QPointF &pos, const qreal newRotation = mOldObjectRotations.at(i) + angleDiff * 180 / M_PI; objectItem->setPos(newPixelPos); -// objectItem->setZValue(newPixelPos.y()); objectItem->mapObject()->setPosition(newPos); objectItem->setObjectRotation(newRotation); + ++i; } } diff --git a/src/tiled/propertybrowser.cpp b/src/tiled/propertybrowser.cpp index 0be261cb19..3abf97f6ac 100644 --- a/src/tiled/propertybrowser.cpp +++ b/src/tiled/propertybrowser.cpp @@ -75,6 +75,9 @@ PropertyBrowser::PropertyBrowser(QWidget *parent) mFlippingFlagNames.append(tr("Horizontal")); mFlippingFlagNames.append(tr("Vertical")); + mDrawOrderNames.append(tr("Top Down")); + mDrawOrderNames.append(tr("Manual")); + connect(mVariantManager, SIGNAL(valueChanged(QtProperty*,QVariant)), SLOT(valueChanged(QtProperty*,QVariant))); } @@ -360,7 +363,17 @@ void PropertyBrowser::addObjectGroupProperties() { QtProperty *groupProperty = mGroupManager->addProperty(tr("Object Layer")); addLayerProperties(groupProperty); + createProperty(ColorProperty, QVariant::Color, tr("Color"), groupProperty); + + QtVariantProperty *drawOrderProperty = + createProperty(DrawOrderProperty, + QtVariantPropertyManager::enumTypeId(), + tr("Drawing Order"), + groupProperty); + + drawOrderProperty->setAttribute(QLatin1String("enumNames"), mDrawOrderNames); + addProperty(groupProperty); } @@ -521,17 +534,34 @@ void PropertyBrowser::applyTileLayerValue(PropertyId id, const QVariant &val) void PropertyBrowser::applyObjectGroupValue(PropertyId id, const QVariant &val) { ObjectGroup *objectGroup = static_cast(mObject); + QUndoCommand *command = 0; - if (id == ColorProperty) { + switch (id) { + case ColorProperty: { QColor color = val.value(); if (color == Qt::gray) color = QColor(); - QUndoStack *undoStack = mMapDocument->undoStack(); - undoStack->push(new ChangeObjectGroupProperties(mMapDocument, - objectGroup, - color)); + command = new ChangeObjectGroupProperties(mMapDocument, + objectGroup, + color, + objectGroup->drawOrder()); + break; + } + case DrawOrderProperty: { + ObjectGroup::DrawOrder drawOrder = static_cast(val.toInt()); + command = new ChangeObjectGroupProperties(mMapDocument, + objectGroup, + objectGroup->color(), + drawOrder); + break; + } + default: + break; } + + if (command) + mMapDocument->undoStack()->push(command); } void PropertyBrowser::applyImageLayerValue(PropertyId id, const QVariant &val) @@ -659,6 +689,7 @@ void PropertyBrowser::updateProperties() if (!color.isValid()) color = Qt::gray; mIdToProperty[ColorProperty]->setValue(color); + mIdToProperty[DrawOrderProperty]->setValue(objectGroup->drawOrder()); break; } case Layer::ImageLayerType: diff --git a/src/tiled/propertybrowser.h b/src/tiled/propertybrowser.h index d3b27491dd..72bd0cb81a 100644 --- a/src/tiled/propertybrowser.h +++ b/src/tiled/propertybrowser.h @@ -100,6 +100,7 @@ private slots: LayerFormatProperty, ImageSourceProperty, FlippingProperty, + DrawOrderProperty, CustomProperty }; @@ -144,6 +145,7 @@ private slots: QStringList mLayerFormatNames; QStringList mFlippingFlagNames; + QStringList mDrawOrderNames; }; } // namespace Internal diff --git a/src/tiled/raiselowerhelper.cpp b/src/tiled/raiselowerhelper.cpp index 86aa959d3c..80688507eb 100644 --- a/src/tiled/raiselowerhelper.cpp +++ b/src/tiled/raiselowerhelper.cpp @@ -33,21 +33,6 @@ namespace Tiled { namespace Internal { -static ObjectGroup *sameObjectGroup(const QSet &selectedItems) -{ - if (selectedItems.isEmpty()) - return 0; - - // All selected objects need to be in the same group - ObjectGroup *group = (*selectedItems.begin())->mapObject()->objectGroup(); - - foreach (const MapObjectItem *item, selectedItems) - if (item->mapObject()->objectGroup() != group) - return 0; - - return group; -} - void RaiseLowerHelper::raise() { if (!initContext()) @@ -117,6 +102,8 @@ void RaiseLowerHelper::raiseToTop() ObjectGroup *objectGroup = sameObjectGroup(selectedItems); if (!objectGroup) return; + if (objectGroup->drawOrder() != ObjectGroup::IndexOrder) + return; RangeSet ranges; foreach (MapObjectItem *item, selectedItems) @@ -158,6 +145,8 @@ void RaiseLowerHelper::lowerToBottom() ObjectGroup *objectGroup = sameObjectGroup(selectedItems); if (!objectGroup) return; + if (objectGroup->drawOrder() != ObjectGroup::IndexOrder) + return; RangeSet ranges; foreach (MapObjectItem *item, selectedItems) @@ -187,6 +176,21 @@ void RaiseLowerHelper::lowerToBottom() QCoreApplication::translate("Undo Commands", "Lower Object To Bottom")); } +ObjectGroup *RaiseLowerHelper::sameObjectGroup(const QSet &items) +{ + if (items.isEmpty()) + return 0; + + // All selected objects need to be in the same group + ObjectGroup *group = (*items.begin())->mapObject()->objectGroup(); + + foreach (const MapObjectItem *item, items) + if (item->mapObject()->objectGroup() != group) + return 0; + + return group; +} + /** * Initializes the context in which objects are being raised or lowered. Only * used for single-step raising and lowering, since the context is not relevant @@ -206,6 +210,9 @@ bool RaiseLowerHelper::initContext() // All selected objects need to be in the same group mObjectGroup = (*selectedItems.begin())->mapObject()->objectGroup(); + if (mObjectGroup->drawOrder() != ObjectGroup::IndexOrder) + return false; + QPainterPath shape; foreach (const MapObjectItem *item, selectedItems) { diff --git a/src/tiled/raiselowerhelper.h b/src/tiled/raiselowerhelper.h index 459b9f752d..52bb8c46de 100644 --- a/src/tiled/raiselowerhelper.h +++ b/src/tiled/raiselowerhelper.h @@ -40,6 +40,10 @@ class MapScene; /** * Implements operations to raise or lower the set of selected objects. + * + * The operations don't do anything when there are multiple object groups + * active in the selection, or when the object group does not use index drawing + * order. */ class RaiseLowerHelper { @@ -55,6 +59,8 @@ class RaiseLowerHelper void raiseToTop(); void lowerToBottom(); + static ObjectGroup *sameObjectGroup(const QSet &items); + private: bool initContext(); void push(const QList &commands, const QString &text);