diff --git a/mapeditor/maphandler.cpp b/mapeditor/maphandler.cpp index 7bbd16af7..c346a932d 100644 --- a/mapeditor/maphandler.cpp +++ b/mapeditor/maphandler.cpp @@ -365,49 +365,39 @@ std::vector & MapHandler::getObjects(int x, int y, int z) return tileObjects[index(x, y, z)]; } -void MapHandler::drawObjects(QPainter & painter, int x, int y, int z, QPointF offset, const std::set & locked) + + +void MapHandler::drawObjects(QPainter & painter, const QRectF & section, int z, std::set & locked) { painter.setRenderHint(QPainter::Antialiasing, false); painter.setRenderHint(QPainter::SmoothPixmapTransform, false); + std::map> objectMap; //following the natural order of int3 we draw from north-west to south-east, in accordance with H3's perspective - for(auto & object : getObjects(x, y, z)) + + int left = static_cast(std::round(section.left()))/tileSize; + int right = static_cast(std::round(section.right()))/tileSize; + int top = static_cast(std::round(section.top()))/tileSize; + int bottom = static_cast(std::round(section.bottom()))/tileSize; + + for(int x = left; x < right; ++x) { - const CGObjectInstance * obj = object.obj; - if(!obj) + for(int y = top; y < bottom; ++y) { - logGlobal->error("Stray map object that isn't fading"); - return; + for(auto & object : getObjects(x, y, z)) + objectMap[object.obj->pos].insert(object.obj); } + } - uint8_t animationFrame = 0; - - auto objData = findObjectBitmap(obj, animationFrame, obj->ID == Obj::HERO ? 2 : 0); - if(obj->ID == Obj::HERO && obj->tempOwner.isValidPlayer()) - objData.flagBitmap = findFlagBitmap(dynamic_cast(obj), 0, obj->tempOwner, 4); - - if(objData.objBitmap) - { - auto pos = obj->anchorPos(); - - painter.drawImage(QPoint(x * tileSize - offset.x(), y * tileSize - offset.y()), *objData.objBitmap, object.rect, Qt::AutoColor | Qt::NoOpaqueDetection); - - if(locked.count(obj)) - { - painter.setCompositionMode(QPainter::CompositionMode_DestinationIn); - painter.fillRect(x * tileSize, y * tileSize, object.rect.width(), object.rect.height(), Qt::Dense4Pattern); - painter.setCompositionMode(QPainter::CompositionMode_SourceOver); - } - - if(objData.flagBitmap) - { - if(x == pos.x && y == pos.y) - painter.drawImage(QPoint((x - 2) * tileSize - offset.x(), (y - 1) * tileSize - offset.y()), *objData.flagBitmap); - } - } + for (auto const& objectsOnTile : objectMap) + { + auto tile = objectsOnTile.first; + auto objects = objectsOnTile.second; + for (const CGObjectInstance * object : objects) + drawObjectAt(painter, object, tile.x, tile.y, section.topLeft(), locked.count(object)); } } -void MapHandler::drawObjectAt(QPainter & painter, const CGObjectInstance * obj, int x, int y, QPointF offset) +void MapHandler::drawObjectAt(QPainter & painter, const CGObjectInstance * obj, int x, int y, QPointF offset, bool locked) { if (!obj) { @@ -423,10 +413,19 @@ void MapHandler::drawObjectAt(QPainter & painter, const CGObjectInstance * obj, if (objData.objBitmap) { - painter.drawImage(QPoint((x + 1) * tileSize - objData.objBitmap->width() - offset.x(), (y + 1) * tileSize - objData.objBitmap->height() - offset.y()), *objData.objBitmap); + QPoint point((x + 1) * tileSize - (objData.objBitmap->width() + offset.x()), (y + 1) * tileSize - (objData.objBitmap->height() + offset.y())); + QRect rect(point, QSize(objData.objBitmap->width(), objData.objBitmap->height())); + painter.drawImage(rect, *objData.objBitmap); + + if (locked) + { + painter.setCompositionMode(QPainter::CompositionMode_DestinationIn); + painter.fillRect(rect, Qt::Dense4Pattern); + painter.setCompositionMode(QPainter::CompositionMode_SourceOver); + } if (objData.flagBitmap) - painter.drawImage(QPoint((x + 1) * tileSize - objData.objBitmap->width() - offset.x(), (y + 1) * tileSize - objData.objBitmap->height() - offset.y()), *objData.flagBitmap); + painter.drawImage(point, *objData.flagBitmap); } } diff --git a/mapeditor/maphandler.h b/mapeditor/maphandler.h index e4bfbf948..ee816f62d 100644 --- a/mapeditor/maphandler.h +++ b/mapeditor/maphandler.h @@ -111,8 +111,8 @@ public: std::set addObject(const CGObjectInstance * object); /// draws all objects on current tile (higher-level logic, unlike other draw*** methods) - void drawObjects(QPainter & painter, int x, int y, int z, QPointF offset, const std::set & locked); - void drawObjectAt(QPainter & painter, const CGObjectInstance * object, int x, int y, QPointF offset); + void drawObjects(QPainter & painter, const QRectF & section, int z, std::set & locked); + void drawObjectAt(QPainter & painter, const CGObjectInstance * object, int x, int y, QPointF offset, bool locked = false); void drawMinimapTile(QPainter & painter, int x, int y, int z); diff --git a/mapeditor/scenelayer.cpp b/mapeditor/scenelayer.cpp index 49a25f452..bf4d29cd9 100644 --- a/mapeditor/scenelayer.cpp +++ b/mapeditor/scenelayer.cpp @@ -545,28 +545,13 @@ ObjectsLayer::ObjectsLayer(MapSceneBase * s): AbstractViewportLayer(s) QGraphicsItem * ObjectsLayer::draw(const QRectF & section) { - int left = toInt(section.left()); - int right = toInt(section.right()); - int top = toInt(section.top()); - int bottom = toInt(section.bottom()); QPixmap pixmap(toInt(section.width()), toInt(section.height())); pixmap.fill(Qt::transparent); if (isShown) { QPainter painter(&pixmap); - - QPointF offset = section.topLeft(); - - int margin = 2; // margin is necessary to properly display flags on heroes on a border between two sections - - for(int x = (left - margin)/tileSize; x < (right + margin)/tileSize; ++x) - { - for(int y = (top - margin)/tileSize; y < (bottom + margin)/tileSize; ++y) - { - handler->drawObjects(painter, x, y, scene->level, offset, lockedObjects); - } - } + handler->drawObjects(painter, section, scene->level, lockedObjects); } QGraphicsPixmapItem * result = scene->addPixmap(pixmap); @@ -586,11 +571,14 @@ void ObjectsLayer::setLockObject(const CGObjectInstance * object, bool lock) lockedObjects.insert(object); else lockedObjects.erase(object); + QRectF area = getObjectArea(object); + redraw({area}); } void ObjectsLayer::unlockAll() { lockedObjects.clear(); + redraw(); } SelectionObjectsLayer::SelectionObjectsLayer(MapSceneBase * s): AbstractViewportLayer(s), newObject(nullptr)