Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
* Added status info for various Stamp Brush, Terrain Brush and Eraser modes (#3092, #4201)
* Added Escape to clear tile selection when any tile related tool is selected (#4243)
* Added Escape to cancel tile selection and shape drawing operations
* Added a "Go to Tile" action to jump to specific coordinates (by PoonamMehan, #4348)
* Made the shortcut for current tool switch to previous tool (#4280)
* Allow canceling Select Same Tile, Magic Wand and Bucket Fill operations with right-click and Escape
* Allow dragging over multiple tiles with Select Same Tile, Magic Wand and Bucket Fill tools (#4276)
Expand Down
1 change: 1 addition & 0 deletions docs/manual/keyboard-shortcuts.rst
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ General
- ``Ctrl + V`` - Paste (tiles, objects or properties)
- ``Del`` - Delete (tiles, objects, properties or layers)
- ``Ctrl + G`` - Toggle displaying of the tile grid
- ``Ctrl + Shift + G`` - Go to a tile by its coordinates
- ``H`` - Toggle highlighting of the current layer
- ``Ctrl + M`` - Invokes :doc:`automapping`
- ``Alt + C`` - Copy current position of mouse cursor to clipboard (in
Expand Down
2 changes: 2 additions & 0 deletions src/tiled/libtilededitor.qbs
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,8 @@ DynamicLibrary {
"tilepainter.h",
"tileselectionitem.cpp",
"tileselectionitem.h",
"tilehighlightitem.cpp",
"tilehighlightitem.h",
"tileselectiontool.cpp",
"tileselectiontool.h",
"tilesetchanges.cpp",
Expand Down
98 changes: 98 additions & 0 deletions src/tiled/locatorwidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,15 @@

#include "documentmanager.h"
#include "filteredit.h"
#include "map.h"
#include "mapdocument.h"
#include "mapitem.h"
#include "maprenderer.h"
#include "mapscene.h"
#include "mapview.h"
#include "preferences.h"
#include "projectmanager.h"
#include "tilehighlightitem.h"
#include "utils.h"

#include <QApplication>
Expand Down Expand Up @@ -398,6 +405,97 @@ void FileLocatorSource::setFilterWords(const QStringList &words)
endResetModel();
}

///////////////////////////////////////////////////////////////////////////////

TileLocatorSource::TileLocatorSource(QObject *parent)
: LocatorSource(parent)
, mDelegate(new QStyledItemDelegate(this))
{}

int TileLocatorSource::rowCount(const QModelIndex &parent) const
{
return (!parent.isValid() && mHasValidCoord) ? 1 : 0;
}

QVariant TileLocatorSource::data(const QModelIndex &index, int role) const
{
if (role == Qt::DisplayRole && index.row() == 0 && mHasValidCoord)
return tr("Go to tile (%1, %2)").arg(mTileX).arg(mTileY);
return QVariant();
}

QAbstractItemDelegate *TileLocatorSource::delegate() const
{
return mDelegate;
}

QString TileLocatorSource::placeholderText() const
{
return tr("Go to tile: x, y");
}

void TileLocatorSource::setFilterWords(const QStringList &words)
{
bool validX = false;
bool validY = false;
int x = 0;
int y = 0;

const QString input = words.join(QStringView());
const int commaIndex = input.indexOf(QLatin1Char(','));
if (commaIndex >= 0 && commaIndex < input.size() - 1) {
x = QStringView(input).left(commaIndex).toInt(&validX);
y = QStringView(input).mid(commaIndex + 1).toInt(&validY);
}

if (!(validX && validY) && words.size() == 2) {
x = words.at(0).toInt(&validX);
y = words.at(1).toInt(&validY);
}

beginResetModel();
mHasValidCoord = validX && validY;
mTileX = x;
mTileY = y;
endResetModel();
}

void TileLocatorSource::activate(const QModelIndex &)
{
auto documentManager = DocumentManager::instance();
auto mapDocument = qobject_cast<MapDocument*>(documentManager->currentDocument());
if (!mapDocument)
return;

const auto *map = mapDocument->map();
if (map->width() < 1 || map->height() < 1)
return;

auto mapView = documentManager->currentMapView();
if (!mapView)
return;

const int x = qBound(0, mTileX, map->width() - 1);
const int y = qBound(0, mTileY, map->height() - 1);

auto renderer = mapDocument->renderer();
QPointF pixelPos = renderer->tileToPixelCoords(x + 0.5, y + 0.5);

if (Layer *layer = mapDocument->currentLayer()) {
mapView->forceCenterOn(pixelPos, *layer);

if (auto mapScene = mapView->mapScene()) {
if (MapItem *mapItem = mapScene->mapItem(mapDocument)) {
auto *highlight = new TileHighlightItem(mapDocument, x, y, mapItem);
highlight->setZValue(10003);
highlight->startBlink();
}
}
} else {
mapView->forceCenterOn(pixelPos);
}
}

} // namespace Tiled

#include "moc_locatorwidget.cpp"
24 changes: 24 additions & 0 deletions src/tiled/locatorwidget.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "projectmodel.h"

class QAbstractItemDelegate;
class QStyledItemDelegate;

namespace Tiled {

Expand Down Expand Up @@ -85,4 +86,27 @@ class FileLocatorSource : public LocatorSource
QVector<ProjectModel::Match> mMatches;
};

class TileLocatorSource : public LocatorSource
{
Q_OBJECT

public:
explicit TileLocatorSource(QObject *parent = nullptr);

int rowCount(const QModelIndex &parent) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;

// LocatorSource
QAbstractItemDelegate *delegate() const override;
QString placeholderText() const override;
void setFilterWords(const QStringList &words) override;
void activate(const QModelIndex &index) override;

private:
QStyledItemDelegate *mDelegate;
bool mHasValidCoord = false;
int mTileX = 0;
int mTileY = 0;
};

} // namespace Tiled
8 changes: 8 additions & 0 deletions src/tiled/mainwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,7 @@ MainWindow::MainWindow(QWidget *parent, Qt::WindowFlags flags)
ActionManager::registerAction(mUi->actionFullScreen, "FullScreen");
ActionManager::registerAction(mUi->actionHighlightCurrentLayer, "HighlightCurrentLayer");
ActionManager::registerAction(mUi->actionHighlightHoveredObject, "HighlightHoveredObject");
ActionManager::registerAction(mUi->actionGoToTile, "GoToTile");
ActionManager::registerAction(mUi->actionLabelForHoveredObject, "LabelForHoveredObject");
ActionManager::registerAction(mUi->actionLabelsForAllObjects, "LabelsForAllObjects");
ActionManager::registerAction(mUi->actionLabelsForSelectedObjects, "LabelsForSelectedObjects");
Expand Down Expand Up @@ -530,6 +531,7 @@ MainWindow::MainWindow(QWidget *parent, Qt::WindowFlags flags)
connect(mUi->actionOpen, &QAction::triggered, this, &MainWindow::openFileDialog);
connect(mUi->actionOpenFileInProject, &QAction::triggered, this, &MainWindow::openFileInProject);
connect(mUi->actionSearchActions, &QAction::triggered, this, &MainWindow::searchActions);
connect(mUi->actionGoToTile, &QAction::triggered, this, &MainWindow::goToTile);
connect(mUi->actionReopenClosedFile, &QAction::triggered, this, &MainWindow::reopenClosedFile);
connect(mUi->actionClearRecentFiles, &QAction::triggered, preferences, &Preferences::clearRecentFiles);
connect(mUi->actionSave, &QAction::triggered, this, &MainWindow::saveFile);
Expand Down Expand Up @@ -1154,6 +1156,11 @@ void MainWindow::searchActions()
showLocatorWidget(new ActionLocatorSource);
}

void MainWindow::goToTile()
{
showLocatorWidget(new TileLocatorSource);
}

void MainWindow::showLocatorWidget(LocatorSource *source)
{
if (mLocatorWidget)
Expand Down Expand Up @@ -2205,6 +2212,7 @@ void MainWindow::updateActions()
mUi->actionOffsetMap->setEnabled(mapDocument);
mUi->actionMapProperties->setEnabled(mapDocument);
mUi->actionAutoMap->setEnabled(mapDocument);
mUi->actionGoToTile->setEnabled(mapDocument);

mUi->menuTileset->menuAction()->setVisible(tilesetDocument);
mUi->actionTilesetProperties->setEnabled(tilesetDocument);
Expand Down
1 change: 1 addition & 0 deletions src/tiled/mainwindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ class TILED_EDITOR_EXPORT MainWindow : public QMainWindow
void openFileDialog();
void openFileInProject();
void searchActions();
void goToTile();
void showLocatorWidget(LocatorSource *source);
bool saveFile();
bool saveFileAs();
Expand Down
10 changes: 10 additions & 0 deletions src/tiled/mainwindow.ui
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,8 @@
<addaction name="actionAutoMap"/>
<addaction name="actionAutoMapWhileDrawing"/>
<addaction name="separator"/>
<addaction name="actionGoToTile"/>
<addaction name="separator"/>
<addaction name="actionMapProperties"/>
</widget>
<widget class="QMenu" name="menuView">
Expand Down Expand Up @@ -823,6 +825,14 @@
<enum>QAction::MenuRole::NoRole</enum>
</property>
</action>
<action name="actionGoToTile">
<property name="text">
<string>Go to &amp;Tile...</string>
</property>
<property name="shortcut">
<string notr="true">Ctrl+Shift+G</string>
</property>
</action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources>
Expand Down
109 changes: 109 additions & 0 deletions src/tiled/tilehighlightitem.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
/*
* tilehighlightitem.cpp
* Copyright 2026, PoonamMehan <poonammehan655@gmail.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/

#include "tilehighlightitem.h"

#include "mapdocument.h"
#include "maprenderer.h"
#include "mapscene.h"

#include <QApplication>
#include <QPainter>
#include <QPalette>
#include <QPropertyAnimation>
#include <QSequentialAnimationGroup>
#include <QStyleOptionGraphicsItem>

using namespace Tiled;

TileHighlightItem::TileHighlightItem(MapDocument *mapDocument,
int tileX, int tileY,
QGraphicsItem *parent)
: QGraphicsObject(parent)
, mMapDocument(mapDocument)
, mTileX(tileX)
, mTileY(tileY)
{
setFlag(QGraphicsItem::ItemUsesExtendedStyleOption);

const QRect b(tileX, tileY, 1, 1);
mBoundingRect = mapDocument->renderer()->boundingRect(b);
mBoundingRect.adjust(-1, -1, 1, 1);
}

void TileHighlightItem::startBlink()
{
updatePosition();

constexpr int blinkDuration = 120;
constexpr int blinkCount = 3;

auto *group = new QSequentialAnimationGroup(this);
for (int i = 0; i < blinkCount; ++i) {
auto *toVisible = new QPropertyAnimation(this, "opacity");
toVisible->setDuration(blinkDuration);
toVisible->setStartValue(0.0);
toVisible->setEndValue(1.0);
group->addAnimation(toVisible);

auto *toHidden = new QPropertyAnimation(this, "opacity");
toHidden->setDuration(blinkDuration);
toHidden->setStartValue(1.0);
toHidden->setEndValue(0.0);
group->addAnimation(toHidden);
}

setOpacity(0.0);
connect(group, &QAbstractAnimation::finished, this, &QObject::deleteLater);
group->start(QAbstractAnimation::DeleteWhenStopped);
}

void TileHighlightItem::updatePosition()
{
if (!mMapDocument)
return;
if (auto currentLayer = mMapDocument->currentLayer())
if (auto mapScene = qobject_cast<MapScene*>(scene()))
setPos(mapScene->absolutePositionForLayer(*currentLayer));
}

QRectF TileHighlightItem::boundingRect() const
{
return mBoundingRect;
}

void TileHighlightItem::paint(QPainter *painter,
const QStyleOptionGraphicsItem *option,
QWidget *)
{
if (!mMapDocument) {
deleteLater();
return;
}
const QRegion region(QRect(mTileX, mTileY, 1, 1));
QColor highlight = QApplication::palette().highlight().color();
highlight.setAlpha(128);

MapRenderer *renderer = mMapDocument->renderer();
renderer->drawTileSelection(painter, region, highlight,
option->exposedRect);
}

#include "moc_tilehighlightitem.cpp"
Loading