diff --git a/src/tiled/abstractobjecttool.cpp b/src/tiled/abstractobjecttool.cpp index 60562f7917..b7576c359e 100644 --- a/src/tiled/abstractobjecttool.cpp +++ b/src/tiled/abstractobjecttool.cpp @@ -86,6 +86,7 @@ void AbstractObjectTool::keyPressed(QKeyEvent *event) duplicateObjects(); return; } + break; } event->ignore(); @@ -133,9 +134,22 @@ ObjectGroup *AbstractObjectTool::currentObjectGroup() const return dynamic_cast(mapDocument()->currentLayer()); } +QList AbstractObjectTool::objectItemsAt(QPointF pos) const +{ + const QList &items = mMapScene->items(pos); + + QList objectList; + for (auto item : items) { + if (MapObjectItem *objectItem = qgraphicsitem_cast(item)) + objectList.append(objectItem); + } + return objectList; +} + MapObjectItem *AbstractObjectTool::topMostObjectItemAt(QPointF pos) const { const QList &items = mMapScene->items(pos); + for (QGraphicsItem *item : items) { if (MapObjectItem *objectItem = qgraphicsitem_cast(item)) return objectItem; diff --git a/src/tiled/abstractobjecttool.h b/src/tiled/abstractobjecttool.h index 37136fc236..92e0cdbd29 100644 --- a/src/tiled/abstractobjecttool.h +++ b/src/tiled/abstractobjecttool.h @@ -65,6 +65,7 @@ class AbstractObjectTool : public AbstractTool MapScene *mapScene() const { return mMapScene; } ObjectGroup *currentObjectGroup() const; + QList objectItemsAt(QPointF pos) const; MapObjectItem *topMostObjectItemAt(QPointF pos) const; private slots: diff --git a/src/tiled/mapobjectitem.h b/src/tiled/mapobjectitem.h index c1ed4f46f4..812ec9b7c3 100644 --- a/src/tiled/mapobjectitem.h +++ b/src/tiled/mapobjectitem.h @@ -107,3 +107,5 @@ class MapObjectItem : public QGraphicsItem } // namespace Internal } // namespace Tiled + +Q_DECLARE_METATYPE(Tiled::Internal::MapObjectItem*) diff --git a/src/tiled/objectselectiontool.cpp b/src/tiled/objectselectiontool.cpp index 73c9586bfe..64fa1b97be 100644 --- a/src/tiled/objectselectiontool.cpp +++ b/src/tiled/objectselectiontool.cpp @@ -47,6 +47,7 @@ #include #include #include +#include #include @@ -533,6 +534,53 @@ void ObjectSelectionTool::mousePressed(QGraphicsSceneMouseEvent *event) break; } + case Qt::RightButton: + if (event->modifiers() & Qt::AltModifier) { + QList underlyingObjects = objectItemsAt(event->scenePos()); + if (underlyingObjects.empty()) + break; + QMenu selectUnderlyingMenu; + + for (int levelNum = 0; levelNum < underlyingObjects.size(); ++levelNum) { + QString objectName = underlyingObjects[levelNum]->mapObject()->name(); + const QString& objectType = underlyingObjects[levelNum]->mapObject()->type(); + if (objectName.isEmpty()) { + if (objectType.isEmpty()) + objectName = tr("Unnamed object"); + else + objectName = tr("Instance of %1").arg(objectType); + } + QString actionName; + if (levelNum < 9) + actionName = tr("&%1) %2").arg(levelNum + 1).arg(objectName); + else + actionName = tr("%1) %2").arg(levelNum + 1).arg(objectName); + QAction *action = selectUnderlyingMenu.addAction(actionName); + action->setData(QVariant::fromValue(underlyingObjects[levelNum])); + } + + QAction *action = selectUnderlyingMenu.exec(event->screenPos()); + + if (!action) + break; + + if (MapObjectItem* objectToBeSelected = action->data().value()) { + auto selection = mapScene()->selectedObjectItems(); + if (event->modifiers() & (Qt::ShiftModifier | Qt::ControlModifier)) { + if (selection.contains(objectToBeSelected)) + selection.remove(objectToBeSelected); + else + selection.insert(objectToBeSelected); + } else { + selection.clear(); + selection.insert(objectToBeSelected); + } + mapScene()->setSelectedObjectItems(selection); + } + } else { + AbstractObjectTool::mousePressed(event); + } + break; default: AbstractObjectTool::mousePressed(event); break; @@ -551,11 +599,24 @@ void ObjectSelectionTool::mouseReleased(QGraphicsSceneMouseEvent *event) break; } const Qt::KeyboardModifiers modifiers = event->modifiers(); + QSet selection = mapScene()->selectedObjectItems(); + if (modifiers & Qt::AltModifier) { + auto underlyingObjects = objectItemsAt(event->scenePos()); + if (underlyingObjects.isEmpty()) + break; + + int lastSelectedIndex = -1; + for (auto selected : selection) + lastSelectedIndex = std::max(lastSelectedIndex, underlyingObjects.indexOf(selected)); + do lastSelectedIndex = (lastSelectedIndex + 1) % underlyingObjects.size(); + while (selection.contains(underlyingObjects.at(lastSelectedIndex)) + && lastSelectedIndex != underlyingObjects.size() - 1); + mClickedObjectItem = underlyingObjects.at(lastSelectedIndex); + } if (mClickedObjectItem) { - QSet selection = mapScene()->selectedObjectItems(); if (modifiers & (Qt::ShiftModifier | Qt::ControlModifier)) { - if (selection.contains(mClickedObjectItem)) - selection.remove(mClickedObjectItem); + if (!(modifiers & Qt::AltModifier) && selection.contains(mClickedObjectItem)) + selection.remove(mClickedObjectItem);// Removal is not supported in alt+click mode else selection.insert(mClickedObjectItem); mapScene()->setSelectedObjectItems(selection);