Skip to content

Commit

Permalink
Map Objects are now in Pixel units internally.
Browse files Browse the repository at this point in the history
  • Loading branch information
mauvecow committed Jan 19, 2014
1 parent cdab08f commit 55e7767
Show file tree
Hide file tree
Showing 8 changed files with 99 additions and 191 deletions.
74 changes: 50 additions & 24 deletions src/libtiled/isometricrenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ QRectF IsometricRenderer::boundingRect(const MapObject *object) const
const int nameHeight = object->name().isEmpty() ? 0 : 15;

if (!object->cell().isEmpty()) {
const QPointF bottomCenter = tileToScreenCoords(object->position());
const QPointF bottomCenter = pixelToScreenCoords(object->position());
const Tile *tile = object->cell().tile;
const QSize imgSize = tile->image().size();
const QPoint tileOffset = tile->tileset()->tileOffset();
Expand All @@ -80,15 +80,15 @@ QRectF IsometricRenderer::boundingRect(const MapObject *object) const
const qreal extraSpace = qMax(objectLineWidth() / 2, qreal(1));
const QPointF &pos = object->position();
const QPolygonF polygon = object->polygon().translated(pos);
const QPolygonF screenPolygon = tileToScreenCoords(polygon);
const QPolygonF screenPolygon = pixelToScreenCoords(polygon);
return screenPolygon.boundingRect().adjusted(-extraSpace,
-extraSpace - nameHeight - 1,
extraSpace,
extraSpace);
} else {
// Take the bounding rect of the projected object, and then add a few
// pixels on all sides to correct for the line width.
const QRectF base = tileRectToScreenPolygon(object->bounds()).boundingRect();
const QRectF base = pixelRectToScreenPolygon(object->bounds()).boundingRect();
const qreal extraSpace = qMax(objectLineWidth() / 2, qreal(1));

return base.adjusted(-extraSpace,
Expand All @@ -106,13 +106,13 @@ QPainterPath IsometricRenderer::shape(const MapObject *object) const
switch (object->shape()) {
case MapObject::Ellipse:
case MapObject::Rectangle:
path.addPolygon(tileRectToScreenPolygon(object->bounds()));
path.addPolygon(pixelRectToScreenPolygon(object->bounds()));
break;
case MapObject::Polygon:
case MapObject::Polyline: {
const QPointF &pos = object->position();
const QPolygonF polygon = object->polygon().translated(pos);
const QPolygonF screenPolygon = tileToScreenCoords(polygon);
const QPolygonF screenPolygon = pixelToScreenCoords(polygon);
if (object->shape() == MapObject::Polygon) {
path.addPolygon(screenPolygon);
} else {
Expand Down Expand Up @@ -281,7 +281,7 @@ void IsometricRenderer::drawMapObject(QPainter *painter,
if (!object->cell().isEmpty()) {
const Tile *tile = object->cell().tile;
const QSize imgSize = tile->size();
const QPointF pos = tileToScreenCoords(object->position());
const QPointF pos = pixelToScreenCoords(object->position());

// Draw the name before the transform is applied
const QFontMetrics fm = painter->fontMetrics();
Expand Down Expand Up @@ -330,9 +330,9 @@ void IsometricRenderer::drawMapObject(QPainter *painter,

switch (object->shape()) {
case MapObject::Ellipse: {
QPointF topLeft(tileToScreenCoords(object->bounds().topLeft()));
QPointF bottomLeft(tileToScreenCoords(object->bounds().bottomLeft()));
QPointF topRight(tileToScreenCoords(object->bounds().topRight()));
QPointF topLeft(pixelToScreenCoords(object->bounds().topLeft()));
QPointF bottomLeft(pixelToScreenCoords(object->bounds().bottomLeft()));
QPointF topRight(pixelToScreenCoords(object->bounds().topRight()));

const qreal headerX = bottomLeft.x();
const qreal headerY = topLeft.y();
Expand All @@ -343,7 +343,7 @@ void IsometricRenderer::drawMapObject(QPainter *painter,
QString name = fm.elidedText(object->name(), Qt::ElideRight,
rect.width() + 2);

QPolygonF polygon = tileRectToScreenPolygon(object->bounds());
QPolygonF polygon = pixelRectToScreenPolygon(object->bounds());

float tw = map()->tileWidth();
float th = map()->tileHeight();
Expand Down Expand Up @@ -396,10 +396,9 @@ void IsometricRenderer::drawMapObject(QPainter *painter,
break;
}
case MapObject::Rectangle: {

QPointF topLeft(tileToScreenCoords(object->bounds().topLeft()));
QPointF bottomLeft(tileToScreenCoords(object->bounds().bottomLeft()));
QPointF topRight(tileToScreenCoords(object->bounds().topRight()));
QPointF topLeft(pixelToScreenCoords(object->bounds().topLeft()));
QPointF bottomLeft(pixelToScreenCoords(object->bounds().bottomLeft()));
QPointF topRight(pixelToScreenCoords(object->bounds().topRight()));

const qreal headerX = bottomLeft.x();
const qreal headerY = topLeft.y();
Expand All @@ -410,7 +409,7 @@ void IsometricRenderer::drawMapObject(QPainter *painter,
QString name = fm.elidedText(object->name(), Qt::ElideRight,
rect.width() + 2);

QPolygonF polygon = tileRectToScreenPolygon(object->bounds());
QPolygonF polygon = pixelRectToScreenPolygon(object->bounds());
painter->drawPolygon(polygon);
if (!name.isEmpty())
painter->drawText(QPointF(headerX, headerY - 5 + shadowOffset), name);
Expand All @@ -428,7 +427,7 @@ void IsometricRenderer::drawMapObject(QPainter *painter,
case MapObject::Polygon: {
const QPointF &pos = object->position();
const QPolygonF polygon = object->polygon().translated(pos);
QPolygonF screenPolygon = tileToScreenCoords(polygon);
QPolygonF screenPolygon = pixelToScreenCoords(polygon);

const QRectF polygonBoundingRect = screenPolygon.boundingRect();

Expand Down Expand Up @@ -456,7 +455,7 @@ void IsometricRenderer::drawMapObject(QPainter *painter,
case MapObject::Polyline: {
const QPointF &pos = object->position();
const QPolygonF polygon = object->polygon().translated(pos);
QPolygonF screenPolygon = tileToScreenCoords(polygon);
QPolygonF screenPolygon = pixelToScreenCoords(polygon);

painter->drawPolyline(screenPolygon);

Expand Down Expand Up @@ -510,22 +509,49 @@ QPointF IsometricRenderer::tileToScreenCoords(qreal x, qreal y) const
(x + y) * tileHeight / 2);
}

QPointF IsometricRenderer::pixelToScreenCoords(qreal x, qreal y) const
QPointF IsometricRenderer::screenToPixelCoords(qreal x, qreal y) const
{
const int tileWidth = map()->tileWidth();
const int tileHeight = map()->tileHeight();

x -= map()->height() * tileWidth / 2;

return QPointF((y + x),
(y - x));
const qreal tileY = y / tileHeight;
const qreal tileX = x / tileWidth;

return QPointF((tileY + tileX) * tileHeight,
(tileY - tileX) * tileHeight);
}

QPointF IsometricRenderer::screenToPixelCoords(qreal x, qreal y) const
QPointF IsometricRenderer::pixelToScreenCoords(qreal x, qreal y) const
{
const int tileWidth = map()->tileWidth();
const int tileHeight = map()->tileHeight();
const int originX = map()->height() * tileWidth / 2;
const qreal tileY = y / tileHeight;
const qreal tileX = x / tileHeight;

return QPointF((tileX - tileY) * tileWidth / 2 + originX,
(tileX + tileY) * tileHeight / 2);
}

return QPointF((x - y) / 2 + originX,
(x + y) / 2);
QPolygonF IsometricRenderer::pixelRectToScreenPolygon(const QRect &rect) const
{
QPolygonF polygon;
polygon << QPointF(pixelToScreenCoords(rect.topLeft()));
polygon << QPointF(pixelToScreenCoords(rect.topRight()));
polygon << QPointF(pixelToScreenCoords(rect.bottomRight()));
polygon << QPointF(pixelToScreenCoords(rect.bottomLeft()));
return polygon;
}

QPolygonF IsometricRenderer::pixelRectToScreenPolygon(const QRectF &rect) const
{
QPolygonF polygon;
polygon << QPointF(pixelToScreenCoords(rect.topLeft()));
polygon << QPointF(pixelToScreenCoords(rect.topRight()));
polygon << QPointF(pixelToScreenCoords(rect.bottomRight()));
polygon << QPointF(pixelToScreenCoords(rect.bottomLeft()));
return polygon;
}

QPolygonF IsometricRenderer::tileRectToScreenPolygon(const QRect &rect) const
Expand Down
2 changes: 2 additions & 0 deletions src/libtiled/isometricrenderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ class TILEDSHARED_EXPORT IsometricRenderer : public MapRenderer
QPointF pixelToScreenCoords(qreal x, qreal y) const;

private:
QPolygonF pixelRectToScreenPolygon(const QRect &rect) const;
QPolygonF pixelRectToScreenPolygon(const QRectF &rect) const;
QPolygonF tileRectToScreenPolygon(const QRect &rect) const;
QPolygonF tileRectToScreenPolygon(const QRectF &rect) const;
};
Expand Down
25 changes: 4 additions & 21 deletions src/libtiled/mapreader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -802,22 +802,6 @@ void MapReaderPrivate::readImageLayerImage(ImageLayer *imageLayer)
xml.skipCurrentElement();
}

static QPointF pixelToTileCoordinates(Map *map, qreal x, qreal y)
{
const int tileHeight = map->tileHeight();
const int tileWidth = map->tileWidth();

if (map->orientation() == Map::Isometric) {
// Isometric needs special handling, since the pixel values are based
// solely on the tile height.
return QPointF(x / tileHeight,
y / tileHeight);
} else {
return QPointF(x / tileWidth,
y / tileHeight);
}
}

MapObject *MapReaderPrivate::readObject()
{
Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("object"));
Expand All @@ -832,11 +816,10 @@ MapObject *MapReaderPrivate::readObject()
const QString type = atts.value(QLatin1String("type")).toString();
const QStringRef visibleRef = atts.value(QLatin1String("visible"));

const QPointF pos = pixelToTileCoordinates(mMap, x, y);
const QPointF size = pixelToTileCoordinates(mMap, width, height);
const QPointF pos(x, y);
const QSizeF size(width, height);

MapObject *object = new MapObject(name, type, pos, QSizeF(size.x(),
size.y()));
MapObject *object = new MapObject(name, type, pos, size);

bool ok;
const qreal rotation = atts.value(QLatin1String("rotation")).toString().toDouble(&ok);
Expand Down Expand Up @@ -897,7 +880,7 @@ QPolygonF MapReaderPrivate::readPolygon()
if (!ok)
break;

polygon.append(pixelToTileCoordinates(mMap, x, y));
polygon.append(QPointF(x, y));
}

if (!ok)
Expand Down
16 changes: 8 additions & 8 deletions src/libtiled/maprenderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,14 @@ class TILEDSHARED_EXPORT MapRenderer
inline QPointF pixelToTileCoords(const QPointF &point) const
{ return pixelToTileCoords(point.x(), point.y()); }

QPolygonF pixelToScreenCoords(const QPolygonF &polygon) const
{
QPolygonF screenPolygon(polygon.size());
for (int i = polygon.size() - 1; i >= 0; --i)
screenPolygon[i] = pixelToScreenCoords(polygon[i]);
return screenPolygon;
}

/**
* Returns the pixel coordinates matching the given tile coordinates.
*/
Expand All @@ -171,14 +179,6 @@ class TILEDSHARED_EXPORT MapRenderer
inline QPointF tileToScreenCoords(const QPointF &point) const
{ return tileToScreenCoords(point.x(), point.y()); }

QPolygonF tileToScreenCoords(const QPolygonF &polygon) const
{
QPolygonF screenPolygon(polygon.size());
for (int i = polygon.size() - 1; i >= 0; --i)
screenPolygon[i] = tileToScreenCoords(polygon[i]);
return screenPolygon;
}

/**
* Returns the pixel position matching the given screen position.
*/
Expand Down
46 changes: 4 additions & 42 deletions src/libtiled/mapwriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -499,39 +499,6 @@ void MapWriterPrivate::writeObjectGroup(QXmlStreamWriter &w,
w.writeEndElement();
}

class TileToPixelCoordinates
{
public:
TileToPixelCoordinates(Map *map)
{
if (!map) {
// This is used for objects that are in object groups that are not
// part of a map. This happens with object groups associated with
// tiles, for example.
mMultiplierX = 1;
mMultiplierY = 1;
} else if (map->orientation() == Map::Isometric) {
// Isometric needs special handling, since the pixel values are
// based solely on the tile height.
mMultiplierX = map->tileHeight();
mMultiplierY = map->tileHeight();
} else {
mMultiplierX = map->tileWidth();
mMultiplierY = map->tileHeight();
}
}

QPointF operator() (qreal x, qreal y) const
{
return QPointF(x * mMultiplierX,
y * mMultiplierY);
}

private:
int mMultiplierX;
int mMultiplierY;
};

void MapWriterPrivate::writeObject(QXmlStreamWriter &w,
const MapObject *mapObject)
{
Expand All @@ -548,12 +515,8 @@ void MapWriterPrivate::writeObject(QXmlStreamWriter &w,
w.writeAttribute(QLatin1String("gid"), QString::number(gid));
}

// Convert from tile to pixel coordinates
const ObjectGroup *objectGroup = mapObject->objectGroup();
const TileToPixelCoordinates toPixel(objectGroup->map());

QPointF pos = toPixel(mapObject->x(), mapObject->y());
QPointF size = toPixel(mapObject->width(), mapObject->height());
QPointF pos = QPointF(mapObject->x(), mapObject->y());
QPointF size = QPointF(mapObject->width(), mapObject->height());

w.writeAttribute(QLatin1String("x"), QString::number(pos.x()));
w.writeAttribute(QLatin1String("y"), QString::number(pos.y()));
Expand Down Expand Up @@ -581,10 +544,9 @@ void MapWriterPrivate::writeObject(QXmlStreamWriter &w,

QString points;
foreach (const QPointF &point, polygon) {
const QPointF pos = toPixel(point.x(), point.y());
points.append(QString::number(pos.x()));
points.append(QString::number(point.x()));
points.append(QLatin1Char(','));
points.append(QString::number(pos.y()));
points.append(QString::number(point.y()));
points.append(QLatin1Char(' '));
}
points.chop(1);
Expand Down
Loading

0 comments on commit 55e7767

Please sign in to comment.