From 04678b557640cef1d1cc1a3cbd59da524b3c3084 Mon Sep 17 00:00:00 2001 From: Acuion Date: Thu, 16 Mar 2017 14:58:17 +0300 Subject: [PATCH 01/15] Selection of underlying objects --- src/tiled/abstractobjecttool.cpp | 58 ++++++++++++++++++++++++++++++-- src/tiled/abstractobjecttool.h | 7 +++- 2 files changed, 62 insertions(+), 3 deletions(-) diff --git a/src/tiled/abstractobjecttool.cpp b/src/tiled/abstractobjecttool.cpp index 5ac45c8cac..846bccce31 100644 --- a/src/tiled/abstractobjecttool.cpp +++ b/src/tiled/abstractobjecttool.cpp @@ -67,6 +67,7 @@ AbstractObjectTool::AbstractObjectTool(const QString &name, void AbstractObjectTool::activate(MapScene *scene) { mMapScene = scene; + mSelectedRotationIndex = 0; } void AbstractObjectTool::deactivate(MapScene *) @@ -81,6 +82,19 @@ void AbstractObjectTool::keyPressed(QKeyEvent *event) case Qt::Key_PageDown: lower(); return; case Qt::Key_Home: raiseToTop(); return; case Qt::Key_End: lowerToBottom(); return; + case Qt::Key_Alt: { + auto objectList = listOfObjectItemsAt(mCurrMouseScenePosition); + + if (!objectList.size()) + return; + QSet selection = mapScene()->selectedObjectItems(); + selection.clear(); + selection.insert(objectList.at(mSelectedRotationIndex)); + mapScene()->setSelectedObjectItems(selection); + + mSelectedRotationIndex = (mSelectedRotationIndex + 1) % objectList.size(); + return; + } } event->ignore(); @@ -105,12 +119,15 @@ void AbstractObjectTool::mouseMoved(const QPointF &pos, const int x = (int) std::floor(tilePosF.x()); const int y = (int) std::floor(tilePosF.y()); setStatusInfo(QString(QLatin1String("%1, %2 (%3, %4)")).arg(x).arg(y).arg(pixelPos.x()).arg(pixelPos.y())); + + mCurrMouseScenePosition = pos; + mSelectedRotationIndex = 0; } void AbstractObjectTool::mousePressed(QGraphicsSceneMouseEvent *event) { if (event->button() == Qt::RightButton) { - showContextMenu(topMostObjectItemAt(event->scenePos()), + showContextMenu(event->scenePos(), event->screenPos()); } } @@ -128,9 +145,22 @@ ObjectGroup *AbstractObjectTool::currentObjectGroup() const return dynamic_cast(mapDocument()->currentLayer()); } +QList AbstractObjectTool::listOfObjectItemsAt(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; @@ -205,9 +235,11 @@ void AbstractObjectTool::lowerToBottom() * Shows the context menu for map objects. The menu allows you to duplicate and * remove the map objects, or to edit their properties. */ -void AbstractObjectTool::showContextMenu(MapObjectItem *clickedObjectItem, +void AbstractObjectTool::showContextMenu(QPointF scenePos, QPoint screenPos) { + MapObjectItem *clickedObjectItem = topMostObjectItemAt(scenePos); + QSet selection = mMapScene->selectedObjectItems(); if (clickedObjectItem && !selection.contains(clickedObjectItem)) { selection.clear(); @@ -271,6 +303,21 @@ void AbstractObjectTool::showContextMenu(MapObjectItem *clickedObjectItem, Utils::setThemeIcon(removeAction, "edit-delete"); Utils::setThemeIcon(propertiesAction, "document-properties"); + QList underlyingObjects = listOfObjectItemsAt(scenePos); + if (underlyingObjects.size() > 1) { + menu.addSeparator(); + QMenu *selectUnderlyingMenu = menu.addMenu(tr("Select underlying object")); + + for (int levelNum = 0; levelNum < underlyingObjects.size(); ++levelNum) { + QString actionName = tr("Object at level %n", "", levelNum + 1) + tr(levelNum ? "" : " (topmost)"); + QAction *action = selectUnderlyingMenu->addAction(actionName); + if (levelNum == 0) + action->setEnabled(false);//just to set a starting point + else + action->setData(QVariant::fromValue(levelNum)); + } + } + QAction *action = menu.exec(screenPos); if (!action) return; @@ -286,4 +333,11 @@ void AbstractObjectTool::showContextMenu(MapObjectItem *clickedObjectItem, mapDocument()->moveObjectsToGroup(mapDocument()->selectedObjects(), objectGroup); } + + if (int indexOfObjectToBeSelected = action->data().value()) { + auto selection = mapScene()->selectedObjectItems(); + selection.clear(); + selection.insert(underlyingObjects[indexOfObjectToBeSelected]); + mapScene()->setSelectedObjectItems(selection); + } } diff --git a/src/tiled/abstractobjecttool.h b/src/tiled/abstractobjecttool.h index 37136fc236..84fb5ef337 100644 --- a/src/tiled/abstractobjecttool.h +++ b/src/tiled/abstractobjecttool.h @@ -65,8 +65,11 @@ class AbstractObjectTool : public AbstractTool MapScene *mapScene() const { return mMapScene; } ObjectGroup *currentObjectGroup() const; + QList listOfObjectItemsAt(QPointF pos) const; MapObjectItem *topMostObjectItemAt(QPointF pos) const; + QPointF mCurrMouseScenePosition;//to get the pos in key event + private slots: void duplicateObjects(); void removeObjects(); @@ -81,10 +84,12 @@ private slots: void lowerToBottom(); private: - void showContextMenu(MapObjectItem *clickedObject, + void showContextMenu(QPointF scenePos, QPoint screenPos); MapScene *mMapScene; + + int mSelectedRotationIndex; }; } // namespace Internal From c7c7863526bf50b56f461a2ab8b2cc0139439155 Mon Sep 17 00:00:00 2001 From: Acuion Date: Thu, 16 Mar 2017 15:50:23 +0300 Subject: [PATCH 02/15] Names in submenu --- src/tiled/abstractobjecttool.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/tiled/abstractobjecttool.cpp b/src/tiled/abstractobjecttool.cpp index 846bccce31..15316da607 100644 --- a/src/tiled/abstractobjecttool.cpp +++ b/src/tiled/abstractobjecttool.cpp @@ -306,10 +306,13 @@ void AbstractObjectTool::showContextMenu(QPointF scenePos, QList underlyingObjects = listOfObjectItemsAt(scenePos); if (underlyingObjects.size() > 1) { menu.addSeparator(); + QMenu *selectUnderlyingMenu = menu.addMenu(tr("Select underlying object")); for (int levelNum = 0; levelNum < underlyingObjects.size(); ++levelNum) { - QString actionName = tr("Object at level %n", "", levelNum + 1) + tr(levelNum ? "" : " (topmost)"); + const QString& objectName = underlyingObjects[levelNum]->mapObject()->name(); + QString actionName = (objectName.isEmpty() ? tr("Object at level %n", "", levelNum + 1) : objectName) + + tr(levelNum ? "" : " (topmost)"); QAction *action = selectUnderlyingMenu->addAction(actionName); if (levelNum == 0) action->setEnabled(false);//just to set a starting point From 37481ce7c876b799a531f8864ce27f0201e1e1f9 Mon Sep 17 00:00:00 2001 From: Acuion Date: Fri, 17 Mar 2017 13:24:18 +0300 Subject: [PATCH 03/15] mouse movement without loss of order --- src/tiled/abstractobjecttool.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/tiled/abstractobjecttool.cpp b/src/tiled/abstractobjecttool.cpp index 15316da607..89f755b1ec 100644 --- a/src/tiled/abstractobjecttool.cpp +++ b/src/tiled/abstractobjecttool.cpp @@ -87,6 +87,8 @@ void AbstractObjectTool::keyPressed(QKeyEvent *event) if (!objectList.size()) return; + if (mSelectedRotationIndex >= objectList.size()) + mSelectedRotationIndex = 0;//definitely another stack QSet selection = mapScene()->selectedObjectItems(); selection.clear(); selection.insert(objectList.at(mSelectedRotationIndex)); @@ -121,7 +123,6 @@ void AbstractObjectTool::mouseMoved(const QPointF &pos, setStatusInfo(QString(QLatin1String("%1, %2 (%3, %4)")).arg(x).arg(y).arg(pixelPos.x()).arg(pixelPos.y())); mCurrMouseScenePosition = pos; - mSelectedRotationIndex = 0; } void AbstractObjectTool::mousePressed(QGraphicsSceneMouseEvent *event) @@ -307,7 +308,7 @@ void AbstractObjectTool::showContextMenu(QPointF scenePos, if (underlyingObjects.size() > 1) { menu.addSeparator(); - QMenu *selectUnderlyingMenu = menu.addMenu(tr("Select underlying object")); + QMenu *selectUnderlyingMenu = menu.addMenu(tr("Select an underlying object")); for (int levelNum = 0; levelNum < underlyingObjects.size(); ++levelNum) { const QString& objectName = underlyingObjects[levelNum]->mapObject()->name(); From 85a4260b5ff0e9f98a2f4d72f9127f7dd65e8c9f Mon Sep 17 00:00:00 2001 From: Acuion Date: Fri, 17 Mar 2017 16:23:43 +0300 Subject: [PATCH 04/15] Iterating is now Alt+click --- src/tiled/abstractobjecttool.cpp | 17 +---------------- src/tiled/abstractobjecttool.h | 2 -- src/tiled/objectselectiontool.cpp | 17 ++++++++++++++++- src/tiled/objectselectiontool.h | 2 ++ 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/tiled/abstractobjecttool.cpp b/src/tiled/abstractobjecttool.cpp index 2ba6dbf71d..96266004ab 100644 --- a/src/tiled/abstractobjecttool.cpp +++ b/src/tiled/abstractobjecttool.cpp @@ -67,7 +67,6 @@ AbstractObjectTool::AbstractObjectTool(const QString &name, void AbstractObjectTool::activate(MapScene *scene) { mMapScene = scene; - mSelectedRotationIndex = 0; } void AbstractObjectTool::deactivate(MapScene *) @@ -82,26 +81,12 @@ void AbstractObjectTool::keyPressed(QKeyEvent *event) case Qt::Key_PageDown: lower(); return; case Qt::Key_Home: raiseToTop(); return; case Qt::Key_End: lowerToBottom(); return; - case Qt::Key_Alt: { - auto objectList = listOfObjectItemsAt(mCurrMouseScenePosition); - - if (!objectList.size()) - return; - if (mSelectedRotationIndex >= objectList.size()) - mSelectedRotationIndex = 0;//definitely another stack - QSet selection = mapScene()->selectedObjectItems(); - selection.clear(); - selection.insert(objectList.at(mSelectedRotationIndex)); - mapScene()->setSelectedObjectItems(selection); - - mSelectedRotationIndex = (mSelectedRotationIndex + 1) % objectList.size(); - return; - } case Qt::Key_D: if (event->modifiers() & Qt::ControlModifier) { duplicateObjects(); return; } + return; } event->ignore(); diff --git a/src/tiled/abstractobjecttool.h b/src/tiled/abstractobjecttool.h index 84fb5ef337..ad18f5d22b 100644 --- a/src/tiled/abstractobjecttool.h +++ b/src/tiled/abstractobjecttool.h @@ -88,8 +88,6 @@ private slots: QPoint screenPos); MapScene *mMapScene; - - int mSelectedRotationIndex; }; } // namespace Internal diff --git a/src/tiled/objectselectiontool.cpp b/src/tiled/objectselectiontool.cpp index 73c9586bfe..25b81173b2 100644 --- a/src/tiled/objectselectiontool.cpp +++ b/src/tiled/objectselectiontool.cpp @@ -327,6 +327,7 @@ ObjectSelectionTool::ObjectSelectionTool(QObject *parent) , mResizingLimitVertical(false) , mMode(Resize) , mAction(NoAction) + , mSelectedRotationIndex(0) { for (int i = 0; i < CornerAnchorCount; ++i) mRotateHandles[i] = new RotateHandle(static_cast(i)); @@ -551,8 +552,22 @@ void ObjectSelectionTool::mouseReleased(QGraphicsSceneMouseEvent *event) break; } const Qt::KeyboardModifiers modifiers = event->modifiers(); + QSet selection = mapScene()->selectedObjectItems(); + if (modifiers & Qt::AltModifier) { + auto underlyingObjects = listOfObjectItemsAt(event->scenePos()); + + if (!underlyingObjects.size()) + break; + if (mSelectedRotationIndex >= underlyingObjects.size()) + mSelectedRotationIndex = 0;//definitely another stack + selection.clear(); + selection.insert(underlyingObjects.at(mSelectedRotationIndex)); + mapScene()->setSelectedObjectItems(selection); + + mSelectedRotationIndex = (mSelectedRotationIndex + 1) % underlyingObjects.size(); + break; + } if (mClickedObjectItem) { - QSet selection = mapScene()->selectedObjectItems(); if (modifiers & (Qt::ShiftModifier | Qt::ControlModifier)) { if (selection.contains(mClickedObjectItem)) selection.remove(mClickedObjectItem); diff --git a/src/tiled/objectselectiontool.h b/src/tiled/objectselectiontool.h index 3f0b05a404..4791a3d93e 100644 --- a/src/tiled/objectselectiontool.h +++ b/src/tiled/objectselectiontool.h @@ -157,6 +157,8 @@ private slots: QPointF mStartOffset; QPoint mScreenStart; Qt::KeyboardModifiers mModifiers; + + int mSelectedRotationIndex; }; } // namespace Internal From 874fc7ea8a23682f9d1aeaf0b52a99a7453eddce Mon Sep 17 00:00:00 2001 From: Acuion Date: Fri, 17 Mar 2017 16:25:48 +0300 Subject: [PATCH 05/15] Removed mCurrMouse... --- src/tiled/abstractobjecttool.cpp | 2 -- src/tiled/abstractobjecttool.h | 2 -- 2 files changed, 4 deletions(-) diff --git a/src/tiled/abstractobjecttool.cpp b/src/tiled/abstractobjecttool.cpp index 96266004ab..faf5e12f44 100644 --- a/src/tiled/abstractobjecttool.cpp +++ b/src/tiled/abstractobjecttool.cpp @@ -111,8 +111,6 @@ void AbstractObjectTool::mouseMoved(const QPointF &pos, const int x = (int) std::floor(tilePosF.x()); const int y = (int) std::floor(tilePosF.y()); setStatusInfo(QString(QLatin1String("%1, %2 (%3, %4)")).arg(x).arg(y).arg(pixelPos.x()).arg(pixelPos.y())); - - mCurrMouseScenePosition = pos; } void AbstractObjectTool::mousePressed(QGraphicsSceneMouseEvent *event) diff --git a/src/tiled/abstractobjecttool.h b/src/tiled/abstractobjecttool.h index ad18f5d22b..fe566c7777 100644 --- a/src/tiled/abstractobjecttool.h +++ b/src/tiled/abstractobjecttool.h @@ -68,8 +68,6 @@ class AbstractObjectTool : public AbstractTool QList listOfObjectItemsAt(QPointF pos) const; MapObjectItem *topMostObjectItemAt(QPointF pos) const; - QPointF mCurrMouseScenePosition;//to get the pos in key event - private slots: void duplicateObjects(); void removeObjects(); From cf1117f799a2341c3c89b512d816c91260f8942f Mon Sep 17 00:00:00 2001 From: Acuion Date: Fri, 17 Mar 2017 16:30:52 +0300 Subject: [PATCH 06/15] codestyle --- src/tiled/abstractobjecttool.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/tiled/abstractobjecttool.cpp b/src/tiled/abstractobjecttool.cpp index faf5e12f44..91d129d028 100644 --- a/src/tiled/abstractobjecttool.cpp +++ b/src/tiled/abstractobjecttool.cpp @@ -116,8 +116,7 @@ void AbstractObjectTool::mouseMoved(const QPointF &pos, void AbstractObjectTool::mousePressed(QGraphicsSceneMouseEvent *event) { if (event->button() == Qt::RightButton) { - showContextMenu(event->scenePos(), - event->screenPos()); + showContextMenu(event->scenePos(), event->screenPos()); } } @@ -224,8 +223,7 @@ void AbstractObjectTool::lowerToBottom() * Shows the context menu for map objects. The menu allows you to duplicate and * remove the map objects, or to edit their properties. */ -void AbstractObjectTool::showContextMenu(QPointF scenePos, - QPoint screenPos) +void AbstractObjectTool::showContextMenu(QPointF scenePos, QPoint screenPos) { MapObjectItem *clickedObjectItem = topMostObjectItemAt(scenePos); From cea4d0a1506727f4b4dcb76c65848f0eb78462c0 Mon Sep 17 00:00:00 2001 From: Acuion Date: Fri, 17 Mar 2017 18:49:14 +0300 Subject: [PATCH 07/15] Not my code, but a little refactoring --- src/tiled/abstractobjecttool.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/tiled/abstractobjecttool.cpp b/src/tiled/abstractobjecttool.cpp index 91d129d028..8fdff9e308 100644 --- a/src/tiled/abstractobjecttool.cpp +++ b/src/tiled/abstractobjecttool.cpp @@ -82,10 +82,8 @@ void AbstractObjectTool::keyPressed(QKeyEvent *event) case Qt::Key_Home: raiseToTop(); return; case Qt::Key_End: lowerToBottom(); return; case Qt::Key_D: - if (event->modifiers() & Qt::ControlModifier) { + if (event->modifiers() & Qt::ControlModifier) duplicateObjects(); - return; - } return; } From 9c5dcfbb0b02ec7d01218158e0da5888090f42bf Mon Sep 17 00:00:00 2001 From: Acuion Date: Sat, 18 Mar 2017 13:52:27 +0300 Subject: [PATCH 08/15] return of the return, lol --- src/tiled/abstractobjecttool.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/tiled/abstractobjecttool.cpp b/src/tiled/abstractobjecttool.cpp index 8fdff9e308..1ef9f567a4 100644 --- a/src/tiled/abstractobjecttool.cpp +++ b/src/tiled/abstractobjecttool.cpp @@ -82,9 +82,11 @@ void AbstractObjectTool::keyPressed(QKeyEvent *event) case Qt::Key_Home: raiseToTop(); return; case Qt::Key_End: lowerToBottom(); return; case Qt::Key_D: - if (event->modifiers() & Qt::ControlModifier) + if (event->modifiers() & Qt::ControlModifier) { duplicateObjects(); - return; + return; + } + break; } event->ignore(); From ff0a8edb1a679142bda856c50229943c5206ce66 Mon Sep 17 00:00:00 2001 From: Acuion Date: Sat, 18 Mar 2017 15:26:00 +0300 Subject: [PATCH 09/15] Rotation is now based on pointer, shift/ctrl support --- src/tiled/abstractobjecttool.cpp | 27 +------------ src/tiled/abstractobjecttool.h | 5 +-- src/tiled/mapobjectitem.h | 2 + src/tiled/objectselectiontool.cpp | 65 +++++++++++++++++++++++++------ src/tiled/objectselectiontool.h | 3 +- 5 files changed, 61 insertions(+), 41 deletions(-) diff --git a/src/tiled/abstractobjecttool.cpp b/src/tiled/abstractobjecttool.cpp index 1ef9f567a4..95eb29de21 100644 --- a/src/tiled/abstractobjecttool.cpp +++ b/src/tiled/abstractobjecttool.cpp @@ -133,7 +133,7 @@ ObjectGroup *AbstractObjectTool::currentObjectGroup() const return dynamic_cast(mapDocument()->currentLayer()); } -QList AbstractObjectTool::listOfObjectItemsAt(QPointF pos) const +QList AbstractObjectTool::objectItemsAt(QPointF pos) const { const QList &items = mMapScene->items(pos); @@ -290,24 +290,6 @@ void AbstractObjectTool::showContextMenu(QPointF scenePos, QPoint screenPos) Utils::setThemeIcon(removeAction, "edit-delete"); Utils::setThemeIcon(propertiesAction, "document-properties"); - QList underlyingObjects = listOfObjectItemsAt(scenePos); - if (underlyingObjects.size() > 1) { - menu.addSeparator(); - - QMenu *selectUnderlyingMenu = menu.addMenu(tr("Select an underlying object")); - - for (int levelNum = 0; levelNum < underlyingObjects.size(); ++levelNum) { - const QString& objectName = underlyingObjects[levelNum]->mapObject()->name(); - QString actionName = (objectName.isEmpty() ? tr("Object at level %n", "", levelNum + 1) : objectName) - + tr(levelNum ? "" : " (topmost)"); - QAction *action = selectUnderlyingMenu->addAction(actionName); - if (levelNum == 0) - action->setEnabled(false);//just to set a starting point - else - action->setData(QVariant::fromValue(levelNum)); - } - } - QAction *action = menu.exec(screenPos); if (!action) return; @@ -323,11 +305,4 @@ void AbstractObjectTool::showContextMenu(QPointF scenePos, QPoint screenPos) mapDocument()->moveObjectsToGroup(mapDocument()->selectedObjects(), objectGroup); } - - if (int indexOfObjectToBeSelected = action->data().value()) { - auto selection = mapScene()->selectedObjectItems(); - selection.clear(); - selection.insert(underlyingObjects[indexOfObjectToBeSelected]); - mapScene()->setSelectedObjectItems(selection); - } } diff --git a/src/tiled/abstractobjecttool.h b/src/tiled/abstractobjecttool.h index fe566c7777..4d7dd021ed 100644 --- a/src/tiled/abstractobjecttool.h +++ b/src/tiled/abstractobjecttool.h @@ -65,7 +65,7 @@ class AbstractObjectTool : public AbstractTool MapScene *mapScene() const { return mMapScene; } ObjectGroup *currentObjectGroup() const; - QList listOfObjectItemsAt(QPointF pos) const; + QList objectItemsAt(QPointF pos) const; MapObjectItem *topMostObjectItemAt(QPointF pos) const; private slots: @@ -82,8 +82,7 @@ private slots: void lowerToBottom(); private: - void showContextMenu(QPointF scenePos, - QPoint screenPos); + void showContextMenu(QPointF scenePos, QPoint screenPos); MapScene *mMapScene; }; 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 25b81173b2..7a87809240 100644 --- a/src/tiled/objectselectiontool.cpp +++ b/src/tiled/objectselectiontool.cpp @@ -327,7 +327,7 @@ ObjectSelectionTool::ObjectSelectionTool(QObject *parent) , mResizingLimitVertical(false) , mMode(Resize) , mAction(NoAction) - , mSelectedRotationIndex(0) + , mSelectedInUnderlyingRotation(nullptr) { for (int i = 0; i < CornerAnchorCount; ++i) mRotateHandles[i] = new RotateHandle(static_cast(i)); @@ -534,6 +534,43 @@ void ObjectSelectionTool::mousePressed(QGraphicsSceneMouseEvent *event) break; } + case Qt::RightButton: + if (event->modifiers() & Qt::AltModifier) { + QList underlyingObjects = objectItemsAt(event->scenePos()); + if (underlyingObjects.size() > 1) { + QMenu selectUnderlyingMenu; + + for (int levelNum = 0; levelNum < underlyingObjects.size(); ++levelNum) { + const QString& objectName = underlyingObjects[levelNum]->mapObject()->name(); + QString actionName = (objectName.isEmpty() ? tr("Object at level %n", "", levelNum + 1) : objectName) + + tr(levelNum ? "" : " (topmost)"); + QAction *action = selectUnderlyingMenu.addAction(actionName); + if (levelNum == 0) + action->setEnabled(false);//just to set a starting point + else + action->setData(QVariant::fromValue(underlyingObjects[levelNum])); + } + + QAction *action = selectUnderlyingMenu.exec(event->screenPos()); + + 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; @@ -554,18 +591,24 @@ void ObjectSelectionTool::mouseReleased(QGraphicsSceneMouseEvent *event) const Qt::KeyboardModifiers modifiers = event->modifiers(); QSet selection = mapScene()->selectedObjectItems(); if (modifiers & Qt::AltModifier) { - auto underlyingObjects = listOfObjectItemsAt(event->scenePos()); + auto underlyingObjects = objectItemsAt(event->scenePos()); - if (!underlyingObjects.size()) + if (underlyingObjects.isEmpty()) break; - if (mSelectedRotationIndex >= underlyingObjects.size()) - mSelectedRotationIndex = 0;//definitely another stack - selection.clear(); - selection.insert(underlyingObjects.at(mSelectedRotationIndex)); - mapScene()->setSelectedObjectItems(selection); - - mSelectedRotationIndex = (mSelectedRotationIndex + 1) % underlyingObjects.size(); - break; + auto currRotation = std::find(underlyingObjects.begin(), + underlyingObjects.end(), mSelectedInUnderlyingRotation); + if (currRotation == underlyingObjects.end()) + currRotation = underlyingObjects.begin();//new stack of objects + else { + if ((modifiers & (Qt::ShiftModifier | Qt::ControlModifier)) == 0) { + auto previouslySelected = selection.find(mSelectedInUnderlyingRotation); + if (previouslySelected != selection.end()) + selection.erase(previouslySelected);//deselect previous + } + if (++currRotation == underlyingObjects.end()) + currRotation = underlyingObjects.begin(); + } + mClickedObjectItem = mSelectedInUnderlyingRotation = *currRotation; } if (mClickedObjectItem) { if (modifiers & (Qt::ShiftModifier | Qt::ControlModifier)) { diff --git a/src/tiled/objectselectiontool.h b/src/tiled/objectselectiontool.h index 4791a3d93e..176659ef61 100644 --- a/src/tiled/objectselectiontool.h +++ b/src/tiled/objectselectiontool.h @@ -25,6 +25,7 @@ #include #include #include +#include class QGraphicsItem; @@ -158,7 +159,7 @@ private slots: QPoint mScreenStart; Qt::KeyboardModifiers mModifiers; - int mSelectedRotationIndex; + MapObjectItem *mSelectedInUnderlyingRotation; }; } // namespace Internal From 5a0cf8961da7ccaf3c95e8dee3e7af3667e0cd60 Mon Sep 17 00:00:00 2001 From: Acuion Date: Sat, 18 Mar 2017 15:40:05 +0300 Subject: [PATCH 10/15] First element is now enabled --- src/tiled/objectselectiontool.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/tiled/objectselectiontool.cpp b/src/tiled/objectselectiontool.cpp index 7a87809240..c0063eb165 100644 --- a/src/tiled/objectselectiontool.cpp +++ b/src/tiled/objectselectiontool.cpp @@ -545,10 +545,7 @@ void ObjectSelectionTool::mousePressed(QGraphicsSceneMouseEvent *event) QString actionName = (objectName.isEmpty() ? tr("Object at level %n", "", levelNum + 1) : objectName) + tr(levelNum ? "" : " (topmost)"); QAction *action = selectUnderlyingMenu.addAction(actionName); - if (levelNum == 0) - action->setEnabled(false);//just to set a starting point - else - action->setData(QVariant::fromValue(underlyingObjects[levelNum])); + action->setData(QVariant::fromValue(underlyingObjects[levelNum])); } QAction *action = selectUnderlyingMenu.exec(event->screenPos()); From 6eb96a3cf4d492a0a268994b86a3890f35598d86 Mon Sep 17 00:00:00 2001 From: Acuion Date: Sat, 18 Mar 2017 17:13:01 +0300 Subject: [PATCH 11/15] find&erase->remove --- src/tiled/objectselectiontool.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/tiled/objectselectiontool.cpp b/src/tiled/objectselectiontool.cpp index c0063eb165..dbd10f5531 100644 --- a/src/tiled/objectselectiontool.cpp +++ b/src/tiled/objectselectiontool.cpp @@ -597,11 +597,8 @@ void ObjectSelectionTool::mouseReleased(QGraphicsSceneMouseEvent *event) if (currRotation == underlyingObjects.end()) currRotation = underlyingObjects.begin();//new stack of objects else { - if ((modifiers & (Qt::ShiftModifier | Qt::ControlModifier)) == 0) { - auto previouslySelected = selection.find(mSelectedInUnderlyingRotation); - if (previouslySelected != selection.end()) - selection.erase(previouslySelected);//deselect previous - } + if ((modifiers & (Qt::ShiftModifier | Qt::ControlModifier)) == 0) + selection.remove(mSelectedInUnderlyingRotation);//deselect previous if (++currRotation == underlyingObjects.end()) currRotation = underlyingObjects.begin(); } From 344c0e971d70f364f65c39899b07fe501155c556 Mon Sep 17 00:00:00 2001 From: Acuion Date: Mon, 20 Mar 2017 20:11:48 +0300 Subject: [PATCH 12/15] nullptr check, qt-style finding, unselection opt --- src/tiled/abstractobjecttool.cpp | 8 ++++---- src/tiled/abstractobjecttool.h | 3 ++- src/tiled/objectselectiontool.cpp | 29 ++++++++++++++--------------- src/tiled/objectselectiontool.h | 1 - 4 files changed, 20 insertions(+), 21 deletions(-) diff --git a/src/tiled/abstractobjecttool.cpp b/src/tiled/abstractobjecttool.cpp index 95eb29de21..b7576c359e 100644 --- a/src/tiled/abstractobjecttool.cpp +++ b/src/tiled/abstractobjecttool.cpp @@ -116,7 +116,8 @@ void AbstractObjectTool::mouseMoved(const QPointF &pos, void AbstractObjectTool::mousePressed(QGraphicsSceneMouseEvent *event) { if (event->button() == Qt::RightButton) { - showContextMenu(event->scenePos(), event->screenPos()); + showContextMenu(topMostObjectItemAt(event->scenePos()), + event->screenPos()); } } @@ -223,10 +224,9 @@ void AbstractObjectTool::lowerToBottom() * Shows the context menu for map objects. The menu allows you to duplicate and * remove the map objects, or to edit their properties. */ -void AbstractObjectTool::showContextMenu(QPointF scenePos, QPoint screenPos) +void AbstractObjectTool::showContextMenu(MapObjectItem *clickedObjectItem, + QPoint screenPos) { - MapObjectItem *clickedObjectItem = topMostObjectItemAt(scenePos); - QSet selection = mMapScene->selectedObjectItems(); if (clickedObjectItem && !selection.contains(clickedObjectItem)) { selection.clear(); diff --git a/src/tiled/abstractobjecttool.h b/src/tiled/abstractobjecttool.h index 4d7dd021ed..92e0cdbd29 100644 --- a/src/tiled/abstractobjecttool.h +++ b/src/tiled/abstractobjecttool.h @@ -82,7 +82,8 @@ private slots: void lowerToBottom(); private: - void showContextMenu(QPointF scenePos, QPoint screenPos); + void showContextMenu(MapObjectItem *clickedObject, + QPoint screenPos); MapScene *mMapScene; }; diff --git a/src/tiled/objectselectiontool.cpp b/src/tiled/objectselectiontool.cpp index dbd10f5531..2f9c5fbbb4 100644 --- a/src/tiled/objectselectiontool.cpp +++ b/src/tiled/objectselectiontool.cpp @@ -47,6 +47,7 @@ #include #include #include +#include #include @@ -537,7 +538,7 @@ void ObjectSelectionTool::mousePressed(QGraphicsSceneMouseEvent *event) case Qt::RightButton: if (event->modifiers() & Qt::AltModifier) { QList underlyingObjects = objectItemsAt(event->scenePos()); - if (underlyingObjects.size() > 1) { + if (!underlyingObjects.empty()) { QMenu selectUnderlyingMenu; for (int levelNum = 0; levelNum < underlyingObjects.size(); ++levelNum) { @@ -550,6 +551,9 @@ void ObjectSelectionTool::mousePressed(QGraphicsSceneMouseEvent *event) 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)) { @@ -589,20 +593,11 @@ void ObjectSelectionTool::mouseReleased(QGraphicsSceneMouseEvent *event) QSet selection = mapScene()->selectedObjectItems(); if (modifiers & Qt::AltModifier) { auto underlyingObjects = objectItemsAt(event->scenePos()); - if (underlyingObjects.isEmpty()) break; - auto currRotation = std::find(underlyingObjects.begin(), - underlyingObjects.end(), mSelectedInUnderlyingRotation); - if (currRotation == underlyingObjects.end()) - currRotation = underlyingObjects.begin();//new stack of objects - else { - if ((modifiers & (Qt::ShiftModifier | Qt::ControlModifier)) == 0) - selection.remove(mSelectedInUnderlyingRotation);//deselect previous - if (++currRotation == underlyingObjects.end()) - currRotation = underlyingObjects.begin(); - } - mClickedObjectItem = mSelectedInUnderlyingRotation = *currRotation; + int currRotationIndex = underlyingObjects.indexOf(mSelectedInUnderlyingRotation); + mClickedObjectItem = mSelectedInUnderlyingRotation + = underlyingObjects.at((currRotationIndex + 1) % underlyingObjects.size()); } if (mClickedObjectItem) { if (modifiers & (Qt::ShiftModifier | Qt::ControlModifier)) { @@ -612,8 +607,12 @@ void ObjectSelectionTool::mouseReleased(QGraphicsSceneMouseEvent *event) selection.insert(mClickedObjectItem); mapScene()->setSelectedObjectItems(selection); } else if (selection.contains(mClickedObjectItem)) { - // Clicking one of the selected items changes the edit mode - setMode((mMode == Resize) ? Rotate : Resize); + if (modifiers & Qt::AltModifier) { + selection.remove(mClickedObjectItem); + } else { + // Clicking one of the selected items changes the edit mode + setMode((mMode == Resize) ? Rotate : Resize); + } } else { selection.clear(); selection.insert(mClickedObjectItem); diff --git a/src/tiled/objectselectiontool.h b/src/tiled/objectselectiontool.h index 176659ef61..090d29018e 100644 --- a/src/tiled/objectselectiontool.h +++ b/src/tiled/objectselectiontool.h @@ -25,7 +25,6 @@ #include #include #include -#include class QGraphicsItem; From 250125d75dcc3b53848e29d9f21d3fd142e93eb8 Mon Sep 17 00:00:00 2001 From: Acuion Date: Mon, 20 Mar 2017 20:25:16 +0300 Subject: [PATCH 13/15] refactoring --- src/tiled/objectselectiontool.cpp | 54 +++++++++++++++---------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/src/tiled/objectselectiontool.cpp b/src/tiled/objectselectiontool.cpp index 2f9c5fbbb4..8d64273226 100644 --- a/src/tiled/objectselectiontool.cpp +++ b/src/tiled/objectselectiontool.cpp @@ -538,35 +538,35 @@ void ObjectSelectionTool::mousePressed(QGraphicsSceneMouseEvent *event) case Qt::RightButton: if (event->modifiers() & Qt::AltModifier) { QList underlyingObjects = objectItemsAt(event->scenePos()); - if (!underlyingObjects.empty()) { - QMenu selectUnderlyingMenu; - - for (int levelNum = 0; levelNum < underlyingObjects.size(); ++levelNum) { - const QString& objectName = underlyingObjects[levelNum]->mapObject()->name(); - QString actionName = (objectName.isEmpty() ? tr("Object at level %n", "", levelNum + 1) : objectName) - + tr(levelNum ? "" : " (topmost)"); - QAction *action = selectUnderlyingMenu.addAction(actionName); - action->setData(QVariant::fromValue(underlyingObjects[levelNum])); - } + if (underlyingObjects.empty()) + break; + QMenu selectUnderlyingMenu; + + for (int levelNum = 0; levelNum < underlyingObjects.size(); ++levelNum) { + const QString& objectName = underlyingObjects[levelNum]->mapObject()->name(); + QString actionName = (objectName.isEmpty() ? tr("Object at level %n", "", levelNum + 1) : objectName) + + tr(levelNum ? "" : " (topmost)"); + QAction *action = selectUnderlyingMenu.addAction(actionName); + action->setData(QVariant::fromValue(underlyingObjects[levelNum])); + } + + QAction *action = selectUnderlyingMenu.exec(event->screenPos()); - 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); + 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 From 5459383815edb6e1289d1ea1f55281f1391659f5 Mon Sep 17 00:00:00 2001 From: Acuion Date: Tue, 21 Mar 2017 19:20:22 +0300 Subject: [PATCH 14/15] Selected-based rotation --- src/tiled/objectselectiontool.cpp | 37 +++++++++++++++---------------- src/tiled/objectselectiontool.h | 2 -- 2 files changed, 18 insertions(+), 21 deletions(-) diff --git a/src/tiled/objectselectiontool.cpp b/src/tiled/objectselectiontool.cpp index 8d64273226..d5b6e137db 100644 --- a/src/tiled/objectselectiontool.cpp +++ b/src/tiled/objectselectiontool.cpp @@ -328,7 +328,6 @@ ObjectSelectionTool::ObjectSelectionTool(QObject *parent) , mResizingLimitVertical(false) , mMode(Resize) , mAction(NoAction) - , mSelectedInUnderlyingRotation(nullptr) { for (int i = 0; i < CornerAnchorCount; ++i) mRotateHandles[i] = new RotateHandle(static_cast(i)); @@ -544,8 +543,8 @@ void ObjectSelectionTool::mousePressed(QGraphicsSceneMouseEvent *event) for (int levelNum = 0; levelNum < underlyingObjects.size(); ++levelNum) { const QString& objectName = underlyingObjects[levelNum]->mapObject()->name(); - QString actionName = (objectName.isEmpty() ? tr("Object at level %n", "", levelNum + 1) : objectName) - + tr(levelNum ? "" : " (topmost)"); + QString actionName = QLatin1String(levelNum < 9 ? "&" : "") + tr("%n) ", "", levelNum + 1) + + (objectName.isEmpty() ? tr("Unnamed object") : objectName); QAction *action = selectUnderlyingMenu.addAction(actionName); action->setData(QVariant::fromValue(underlyingObjects[levelNum])); } @@ -559,17 +558,16 @@ void ObjectSelectionTool::mousePressed(QGraphicsSceneMouseEvent *event) auto selection = mapScene()->selectedObjectItems(); if (event->modifiers() & (Qt::ShiftModifier | Qt::ControlModifier)) { if (selection.contains(objectToBeSelected)) - selection.remove(objectToBeSelected); - else - selection.insert(objectToBeSelected); + selection.remove(objectToBeSelected); + else + selection.insert(objectToBeSelected); } else { selection.clear(); selection.insert(objectToBeSelected); } mapScene()->setSelectedObjectItems(selection); } - } - else + } else AbstractObjectTool::mousePressed(event); break; default: @@ -595,24 +593,25 @@ void ObjectSelectionTool::mouseReleased(QGraphicsSceneMouseEvent *event) auto underlyingObjects = objectItemsAt(event->scenePos()); if (underlyingObjects.isEmpty()) break; - int currRotationIndex = underlyingObjects.indexOf(mSelectedInUnderlyingRotation); - mClickedObjectItem = mSelectedInUnderlyingRotation - = underlyingObjects.at((currRotationIndex + 1) % underlyingObjects.size()); + + 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) { 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); } else if (selection.contains(mClickedObjectItem)) { - if (modifiers & Qt::AltModifier) { - selection.remove(mClickedObjectItem); - } else { - // Clicking one of the selected items changes the edit mode - setMode((mMode == Resize) ? Rotate : Resize); - } + // Clicking one of the selected items changes the edit mode + setMode((mMode == Resize) ? Rotate : Resize); } else { selection.clear(); selection.insert(mClickedObjectItem); diff --git a/src/tiled/objectselectiontool.h b/src/tiled/objectselectiontool.h index 090d29018e..3f0b05a404 100644 --- a/src/tiled/objectselectiontool.h +++ b/src/tiled/objectselectiontool.h @@ -157,8 +157,6 @@ private slots: QPointF mStartOffset; QPoint mScreenStart; Qt::KeyboardModifiers mModifiers; - - MapObjectItem *mSelectedInUnderlyingRotation; }; } // namespace Internal From f1c2fa2ffdf04ed5254700d6306afa2550af2cde Mon Sep 17 00:00:00 2001 From: Acuion Date: Wed, 22 Mar 2017 08:36:58 +0300 Subject: [PATCH 15/15] Object name and codestyle --- src/tiled/objectselectiontool.cpp | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/tiled/objectselectiontool.cpp b/src/tiled/objectselectiontool.cpp index d5b6e137db..64fa1b97be 100644 --- a/src/tiled/objectselectiontool.cpp +++ b/src/tiled/objectselectiontool.cpp @@ -542,9 +542,19 @@ void ObjectSelectionTool::mousePressed(QGraphicsSceneMouseEvent *event) QMenu selectUnderlyingMenu; for (int levelNum = 0; levelNum < underlyingObjects.size(); ++levelNum) { - const QString& objectName = underlyingObjects[levelNum]->mapObject()->name(); - QString actionName = QLatin1String(levelNum < 9 ? "&" : "") + tr("%n) ", "", levelNum + 1) - + (objectName.isEmpty() ? tr("Unnamed object") : objectName); + 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])); } @@ -567,8 +577,9 @@ void ObjectSelectionTool::mousePressed(QGraphicsSceneMouseEvent *event) } mapScene()->setSelectedObjectItems(selection); } - } else + } else { AbstractObjectTool::mousePressed(event); + } break; default: AbstractObjectTool::mousePressed(event);