mirror of
https://github.com/vcmi/vcmi.git
synced 2025-11-27 22:49:25 +02:00
Rework drawing objects and fix drawing locked objects
This commit is contained in:
@@ -365,49 +365,39 @@ std::vector<ObjectRect> & MapHandler::getObjects(int x, int y, int z)
|
|||||||
return tileObjects[index(x, y, z)];
|
return tileObjects[index(x, y, z)];
|
||||||
}
|
}
|
||||||
|
|
||||||
void MapHandler::drawObjects(QPainter & painter, int x, int y, int z, QPointF offset, const std::set<const CGObjectInstance *> & locked)
|
|
||||||
|
|
||||||
|
void MapHandler::drawObjects(QPainter & painter, const QRectF & section, int z, std::set<const CGObjectInstance *> & locked)
|
||||||
{
|
{
|
||||||
painter.setRenderHint(QPainter::Antialiasing, false);
|
painter.setRenderHint(QPainter::Antialiasing, false);
|
||||||
painter.setRenderHint(QPainter::SmoothPixmapTransform, false);
|
painter.setRenderHint(QPainter::SmoothPixmapTransform, false);
|
||||||
|
std::map<int3, std::set<const CGObjectInstance *>> 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<int>(std::round(section.left()))/tileSize;
|
||||||
|
int right = static_cast<int>(std::round(section.right()))/tileSize;
|
||||||
|
int top = static_cast<int>(std::round(section.top()))/tileSize;
|
||||||
|
int bottom = static_cast<int>(std::round(section.bottom()))/tileSize;
|
||||||
|
|
||||||
|
for(int x = left; x < right; ++x)
|
||||||
{
|
{
|
||||||
const CGObjectInstance * obj = object.obj;
|
for(int y = top; y < bottom; ++y)
|
||||||
if(!obj)
|
|
||||||
{
|
{
|
||||||
logGlobal->error("Stray map object that isn't fading");
|
for(auto & object : getObjects(x, y, z))
|
||||||
return;
|
objectMap[object.obj->pos].insert(object.obj);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t animationFrame = 0;
|
for (auto const& objectsOnTile : objectMap)
|
||||||
|
{
|
||||||
auto objData = findObjectBitmap(obj, animationFrame, obj->ID == Obj::HERO ? 2 : 0);
|
auto tile = objectsOnTile.first;
|
||||||
if(obj->ID == Obj::HERO && obj->tempOwner.isValidPlayer())
|
auto objects = objectsOnTile.second;
|
||||||
objData.flagBitmap = findFlagBitmap(dynamic_cast<const CGHeroInstance*>(obj), 0, obj->tempOwner, 4);
|
for (const CGObjectInstance * object : objects)
|
||||||
|
drawObjectAt(painter, object, tile.x, tile.y, section.topLeft(), locked.count(object));
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
if (!obj)
|
||||||
{
|
{
|
||||||
@@ -423,10 +413,19 @@ void MapHandler::drawObjectAt(QPainter & painter, const CGObjectInstance * obj,
|
|||||||
|
|
||||||
if (objData.objBitmap)
|
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)
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -111,8 +111,8 @@ public:
|
|||||||
std::set<int3> addObject(const CGObjectInstance * object);
|
std::set<int3> addObject(const CGObjectInstance * object);
|
||||||
|
|
||||||
/// draws all objects on current tile (higher-level logic, unlike other draw*** methods)
|
/// 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<const CGObjectInstance *> & locked);
|
void drawObjects(QPainter & painter, const QRectF & section, int z, std::set<const CGObjectInstance *> & locked);
|
||||||
void drawObjectAt(QPainter & painter, const CGObjectInstance * object, int x, int y, QPointF offset);
|
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);
|
void drawMinimapTile(QPainter & painter, int x, int y, int z);
|
||||||
|
|
||||||
|
|||||||
@@ -545,28 +545,13 @@ ObjectsLayer::ObjectsLayer(MapSceneBase * s): AbstractViewportLayer(s)
|
|||||||
|
|
||||||
QGraphicsItem * ObjectsLayer::draw(const QRectF & section)
|
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()));
|
QPixmap pixmap(toInt(section.width()), toInt(section.height()));
|
||||||
pixmap.fill(Qt::transparent);
|
pixmap.fill(Qt::transparent);
|
||||||
|
|
||||||
if (isShown)
|
if (isShown)
|
||||||
{
|
{
|
||||||
QPainter painter(&pixmap);
|
QPainter painter(&pixmap);
|
||||||
|
handler->drawObjects(painter, section, scene->level, lockedObjects);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QGraphicsPixmapItem * result = scene->addPixmap(pixmap);
|
QGraphicsPixmapItem * result = scene->addPixmap(pixmap);
|
||||||
@@ -586,11 +571,14 @@ void ObjectsLayer::setLockObject(const CGObjectInstance * object, bool lock)
|
|||||||
lockedObjects.insert(object);
|
lockedObjects.insert(object);
|
||||||
else
|
else
|
||||||
lockedObjects.erase(object);
|
lockedObjects.erase(object);
|
||||||
|
QRectF area = getObjectArea(object);
|
||||||
|
redraw({area});
|
||||||
}
|
}
|
||||||
|
|
||||||
void ObjectsLayer::unlockAll()
|
void ObjectsLayer::unlockAll()
|
||||||
{
|
{
|
||||||
lockedObjects.clear();
|
lockedObjects.clear();
|
||||||
|
redraw();
|
||||||
}
|
}
|
||||||
|
|
||||||
SelectionObjectsLayer::SelectionObjectsLayer(MapSceneBase * s): AbstractViewportLayer(s), newObject(nullptr)
|
SelectionObjectsLayer::SelectionObjectsLayer(MapSceneBase * s): AbstractViewportLayer(s), newObject(nullptr)
|
||||||
|
|||||||
Reference in New Issue
Block a user