Example #1
0
void MapScene::setMapDocument(MapDocument *mapDocument)
{
    if (mMapDocument) {
        mMapDocument->disconnect(this);

        if (!mSelectedObjectItems.isEmpty()) {
            mSelectedObjectItems.clear();
            emit selectedObjectItemsChanged();
        }
    }

    mMapDocument = mapDocument;

    if (mMapDocument) {
        MapRenderer *renderer = mMapDocument->renderer();
        renderer->setObjectLineWidth(mObjectLineWidth);
        renderer->setFlag(ShowTileObjectOutlines, mShowTileObjectOutlines);

        connect(mMapDocument, SIGNAL(mapChanged()),
                this, SLOT(mapChanged()));
        connect(mMapDocument, &MapDocument::regionChanged,
                this, &MapScene::repaintRegion);
        connect(mMapDocument, SIGNAL(tileLayerDrawMarginsChanged(TileLayer*)),
                this, SLOT(tileLayerDrawMarginsChanged(TileLayer*)));
        connect(mMapDocument, SIGNAL(layerAdded(int)),
                this, SLOT(layerAdded(int)));
        connect(mMapDocument, SIGNAL(layerRemoved(int)),
                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)),
                this, SLOT(currentLayerIndexChanged()));
        connect(mMapDocument, SIGNAL(tilesetTileOffsetChanged(Tileset*)),
                this, SLOT(tilesetTileOffsetChanged(Tileset*)));
        connect(mMapDocument, SIGNAL(objectsInserted(ObjectGroup*,int,int)),
                this, SLOT(objectsInserted(ObjectGroup*,int,int)));
        connect(mMapDocument, SIGNAL(objectsRemoved(QList<MapObject*>)),
                this, SLOT(objectsRemoved(QList<MapObject*>)));
        connect(mMapDocument, SIGNAL(objectsChanged(QList<MapObject*>)),
                this, SLOT(objectsChanged(QList<MapObject*>)));
        connect(mMapDocument, SIGNAL(objectsIndexChanged(ObjectGroup*,int,int)),
                this, SLOT(objectsIndexChanged(ObjectGroup*,int,int)));
        connect(mMapDocument, SIGNAL(selectedObjectsChanged()),
                this, SLOT(updateSelectedObjectItems()));
    }

    refreshScene();
}
Example #2
0
void ExportAsImageDialog::accept()
{
    const QString fileName = mUi->fileNameEdit->text();
    if (fileName.isEmpty())
        return;

    if (QFile::exists(fileName)) {
        const QMessageBox::StandardButton button =
                QMessageBox::warning(this,
                                     tr("Export as Image"),
                                     tr("%1 already exists.\n"
                                        "Do you want to replace it?")
                                     .arg(QFileInfo(fileName).fileName()),
                                     QMessageBox::Yes | QMessageBox::No,
                                     QMessageBox::No);

        if (button != QMessageBox::Yes)
            return;
    }

    const bool visibleLayersOnly = mUi->visibleLayersOnly->isChecked();
    const bool useCurrentScale = mUi->currentZoomLevel->isChecked();
    const bool drawTileGrid = mUi->drawTileGrid->isChecked();
    const bool includeBackgroundColor = mUi->includeBackgroundColor->isChecked();

    MapRenderer *renderer = mMapDocument->renderer();

    // Remember the current render flags
    const Tiled::RenderFlags renderFlags = renderer->flags();

    renderer->setFlag(ShowTileObjectOutlines, false);

    QSize mapSize = renderer->mapSize();

    QMargins margins = mMapDocument->map()->computeLayerOffsetMargins();
    mapSize.setWidth(mapSize.width() + margins.left() + margins.right());
    mapSize.setHeight(mapSize.height() + margins.top() + margins.bottom());

    if (useCurrentScale)
        mapSize *= mCurrentScale;

    QImage image;

    try {
        image = QImage(mapSize, QImage::Format_ARGB32_Premultiplied);

        if (includeBackgroundColor) {
            if (mMapDocument->map()->backgroundColor().isValid())
                image.fill(mMapDocument->map()->backgroundColor());
            else
                image.fill(Qt::gray);
        } else {
            image.fill(Qt::transparent);
        }
    } catch (const std::bad_alloc &) {
        QMessageBox::critical(this,
                              tr("Out of Memory"),
                              tr("Could not allocate sufficient memory for the image. "
                                 "Try reducing the zoom level or using a 64-bit version of Tiled."));
        return;
    }

    if (image.isNull()) {
        const size_t gigabyte = 1073741824;
        const size_t memory = size_t(mapSize.width()) * size_t(mapSize.height()) * 4;
        const double gigabytes = (double) memory / gigabyte;

        QMessageBox::critical(this,
                              tr("Image too Big"),
                              tr("The resulting image would be %1 x %2 pixels and take %3 GB of memory. "
                                 "Tiled is unable to create such an image. Try reducing the zoom level.")
                              .arg(mapSize.width())
                              .arg(mapSize.height())
                              .arg(gigabytes, 0, 'f', 2));
        return;
    }

    QPainter painter(&image);

    if (useCurrentScale) {
        if (smoothTransform(mCurrentScale))
            painter.setRenderHints(QPainter::SmoothPixmapTransform);

        painter.setTransform(QTransform::fromScale(mCurrentScale,
                                                   mCurrentScale));
        renderer->setPainterScale(mCurrentScale);
    } else {
        renderer->setPainterScale(1);
    }

    painter.translate(margins.left(), margins.top());

    foreach (const Layer *layer, mMapDocument->map()->layers()) {
        if (visibleLayersOnly && !layer->isVisible())
            continue;

        painter.setOpacity(layer->opacity());
        painter.translate(layer->offset());

        const TileLayer *tileLayer = dynamic_cast<const TileLayer*>(layer);
        const ObjectGroup *objGroup = dynamic_cast<const ObjectGroup*>(layer);
        const ImageLayer *imageLayer = dynamic_cast<const ImageLayer*>(layer);

        if (tileLayer) {
            renderer->drawTileLayer(&painter, tileLayer);
        } else if (objGroup) {
            QList<MapObject*> objects = objGroup->objects();

            if (objGroup->drawOrder() == ObjectGroup::TopDownOrder)
                qStableSort(objects.begin(), objects.end(), objectLessThan);

            foreach (const MapObject *object, objects) {
                if (object->isVisible()) {
                    if (object->rotation() != qreal(0)) {
                        QPointF origin = renderer->pixelToScreenCoords(object->position());
                        painter.save();
                        painter.translate(origin);
                        painter.rotate(object->rotation());
                        painter.translate(-origin);
                    }

                    const QColor color = MapObjectItem::objectColor(object);
                    renderer->drawMapObject(&painter, object, color);

                    if (object->rotation() != qreal(0))
                        painter.restore();
                }
            }
        } else if (imageLayer) {
            renderer->drawImageLayer(&painter, imageLayer);
        }

        painter.translate(-layer->offset());
    }
void SaveAsImageDialog::accept() {
    const QString fileName = ui->name->text();
    if (fileName.isEmpty())
        return;

    if (QFile::exists(fileName)) {
        const QMessageBox::StandardButton button =
                QMessageBox::warning(this,
                                     tr("Save as Image"),
                                     tr("%1 already exists.\n"
                                        "Do you want to replace it?")
                                     .arg(QFileInfo(fileName).fileName()),
                                     QMessageBox::Yes | QMessageBox::No,
                                     QMessageBox::No);

        if (button != QMessageBox::Yes)
            return;
    }

    const bool visibleLayersOnly = ui->visibleLayers->isChecked();
    const bool useCurrentScale = ui->currentZoomLevel->isChecked();
    const bool drawTileGrid = ui->showGrid->isChecked();

    MapRenderer *renderer = mMapEditor->renderer();

    //remember the current render flags
    const Aurora::RenderFlags renderFlags = renderer->flags();

    renderer->setFlag(ShowTileObjectOutlines, false);

    QSize mapSize = renderer->mapSize();
    if (useCurrentScale)
        mapSize *= mCurrentScale;

    QImage image(mapSize, QImage::Format_ARGB32);
    image.fill(Qt::transparent);
    QPainter painter(&image);

    if (useCurrentScale && mCurrentScale != qreal(1)) {
        painter.setRenderHints(QPainter::SmoothPixmapTransform |
                               QPainter::HighQualityAntialiasing);
        painter.setTransform(QTransform::fromScale(mCurrentScale,
                                                   mCurrentScale));
    }

    foreach (const Layer *layer, mMapEditor->map()->layers()) {
        if (visibleLayersOnly && !layer->isVisible())
            continue;

        painter.setOpacity(layer->opacity());

        const Tilelayer *tilelayer = dynamic_cast<const Tilelayer*>(layer);

        if (tilelayer) {
            renderer->drawTilelayer(&painter, tilelayer);
        }
    }

    if (drawTileGrid) {
        renderer->drawGrid(&painter, QRectF(QPointF(), renderer->mapSize()));
    }

    //restore the previous render flags
    renderer->setFlags(renderFlags);

    image.save(fileName);
    mPath = QFileInfo(fileName).path();

    //store settings for next time
    QSettings *s = Preferences::instance()->settings();
    s->setValue(QLatin1String(VISIBLE_ONLY_KEY), visibleLayersOnly);
    s->setValue(QLatin1String(CURRENT_SCALE_KEY), useCurrentScale);
    s->setValue(QLatin1String(DRAW_GRID_KEY), drawTileGrid);

    QDialog::accept();
}