2022-10-13 01:51:55 +04:00
|
|
|
/*
|
|
|
|
|
* scenelayer.cpp, part of VCMI engine
|
|
|
|
|
*
|
|
|
|
|
* Authors: listed in file AUTHORS in main folder
|
|
|
|
|
*
|
|
|
|
|
* License: GNU General Public License v2.0 or later
|
|
|
|
|
* Full text of license available in license.txt file, in main folder
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
2022-09-18 03:23:17 +04:00
|
|
|
#include "StdInc.h"
|
|
|
|
|
#include "scenelayer.h"
|
|
|
|
|
#include "mainwindow.h"
|
|
|
|
|
#include "../lib/mapping/CMapEditManager.h"
|
2023-05-24 02:05:59 +03:00
|
|
|
#include "../lib/mapping/CMap.h"
|
2022-09-18 03:23:17 +04:00
|
|
|
#include "inspector/inspector.h"
|
|
|
|
|
#include "mapview.h"
|
|
|
|
|
#include "mapcontroller.h"
|
|
|
|
|
|
|
|
|
|
AbstractLayer::AbstractLayer(MapSceneBase * s): scene(s)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AbstractLayer::initialize(MapController & controller)
|
|
|
|
|
{
|
|
|
|
|
map = controller.map();
|
|
|
|
|
handler = controller.mapHandler();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AbstractLayer::show(bool show)
|
|
|
|
|
{
|
|
|
|
|
isShown = show;
|
2025-10-06 20:33:09 +02:00
|
|
|
|
2022-09-18 03:23:17 +04:00
|
|
|
redraw();
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-06 20:33:09 +02:00
|
|
|
|
|
|
|
|
int AbstractLayer::mapWidthPx() const
|
|
|
|
|
{
|
|
|
|
|
return map ? map->width * tileSize : 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int AbstractLayer::mapHeightPx() const
|
|
|
|
|
{
|
|
|
|
|
return map ? map->height * tileSize : 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int AbstractLayer::toInt(double value) const
|
|
|
|
|
{
|
|
|
|
|
return static_cast<int>(std::round(value)); // is rounded explicitly in order to avoid rounding down unprecise double values
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AbstractFixedLayer::AbstractFixedLayer(MapSceneBase * s): AbstractLayer(s)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AbstractFixedLayer::redraw()
|
2022-09-18 03:23:17 +04:00
|
|
|
{
|
|
|
|
|
if(item)
|
|
|
|
|
{
|
|
|
|
|
if(pixmap && isShown)
|
|
|
|
|
item->setPixmap(*pixmap);
|
|
|
|
|
else
|
|
|
|
|
item->setPixmap(emptyPixmap);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if(pixmap && isShown)
|
|
|
|
|
item.reset(scene->addPixmap(*pixmap));
|
|
|
|
|
else
|
|
|
|
|
item.reset(scene->addPixmap(emptyPixmap));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-06 20:33:09 +02:00
|
|
|
AbstractViewportLayer::AbstractViewportLayer(MapSceneBase * s): AbstractLayer(s)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AbstractViewportLayer::createLayer()
|
2022-09-18 03:23:17 +04:00
|
|
|
{
|
2025-10-06 20:33:09 +02:00
|
|
|
QList<QGraphicsItem *>emptyList;
|
|
|
|
|
items.reset(scene->createItemGroup(emptyList));
|
2022-09-18 03:23:17 +04:00
|
|
|
}
|
|
|
|
|
|
2025-10-06 20:33:09 +02:00
|
|
|
void AbstractViewportLayer::setViewport(const QRectF & viewPort)
|
2022-09-18 03:23:17 +04:00
|
|
|
{
|
|
|
|
|
if(!map)
|
|
|
|
|
return;
|
2025-10-06 20:33:09 +02:00
|
|
|
if (items->boundingRect().contains(viewPort))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
std::vector<QGraphicsItem *> outOfScreenSectors;
|
|
|
|
|
for (QGraphicsItem * sector : getAllSectors())
|
2022-09-18 03:23:17 +04:00
|
|
|
{
|
2025-10-06 20:33:09 +02:00
|
|
|
if (!viewPort.intersects(sector->sceneBoundingRect()))
|
|
|
|
|
outOfScreenSectors.push_back(sector);
|
2022-09-18 03:23:17 +04:00
|
|
|
}
|
2025-10-06 20:33:09 +02:00
|
|
|
for (QGraphicsItem * sector : outOfScreenSectors)
|
2022-09-18 03:23:17 +04:00
|
|
|
{
|
2025-10-06 20:33:09 +02:00
|
|
|
removeSector(sector);
|
2022-09-18 03:23:17 +04:00
|
|
|
}
|
2025-10-06 20:33:09 +02:00
|
|
|
|
|
|
|
|
std::vector<QRectF> newAreas;
|
|
|
|
|
|
|
|
|
|
int left = toInt(viewPort.left());
|
|
|
|
|
int right = toInt(viewPort.right());
|
|
|
|
|
int top = toInt(viewPort.top());
|
|
|
|
|
int bottom = toInt(viewPort.bottom());
|
|
|
|
|
int startX = left - (left % sectorSize);
|
|
|
|
|
int limitX = std::min(right + (sectorSize - right % sectorSize), mapWidthPx());
|
|
|
|
|
int startY = top - (top % sectorSize);
|
|
|
|
|
int limitY = std::min(bottom + (sectorSize - bottom % sectorSize), mapHeightPx());
|
|
|
|
|
|
|
|
|
|
for (int x = startX; x < limitX; x += sectorSize)
|
|
|
|
|
{
|
|
|
|
|
for (int y = startY; y < limitY; y += sectorSize)
|
|
|
|
|
{
|
|
|
|
|
int width = x + sectorSize < limitX ? sectorSize : limitX - x;
|
|
|
|
|
int height = y + sectorSize < limitY ? sectorSize : limitY - y;
|
|
|
|
|
QRectF area(x, y, width, height);
|
|
|
|
|
if (!items->boundingRect().intersects(area))
|
|
|
|
|
newAreas.emplace_back(area);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for(QRectF newSection : newAreas)
|
|
|
|
|
{
|
|
|
|
|
QGraphicsItem * sector = draw(newSection);
|
|
|
|
|
if (sector)
|
|
|
|
|
addSector(sector);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AbstractViewportLayer::update()
|
|
|
|
|
{
|
2022-09-18 03:23:17 +04:00
|
|
|
redraw();
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-06 20:33:09 +02:00
|
|
|
void AbstractViewportLayer::redraw()
|
|
|
|
|
{
|
|
|
|
|
std::set<QGraphicsItem *> allSectors;
|
|
|
|
|
for (auto * sector : getAllSectors())
|
|
|
|
|
allSectors.insert(sector);
|
|
|
|
|
redrawSectors(allSectors);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AbstractViewportLayer::redraw(const std::vector<int3> & tiles)
|
|
|
|
|
{
|
|
|
|
|
std::set<QGraphicsItem *> sectorsToRedraw = getContainingSectors(tiles);
|
|
|
|
|
redrawSectors(sectorsToRedraw);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AbstractViewportLayer::redrawWithSurroundingTiles(const std::vector<int3> & tiles)
|
|
|
|
|
{
|
|
|
|
|
int maxX = 0;
|
|
|
|
|
int maxY = 0;
|
|
|
|
|
int minX = INT_MAX;
|
|
|
|
|
int minY = INT_MAX;
|
|
|
|
|
for (const int3 tile : tiles)
|
|
|
|
|
{
|
|
|
|
|
maxX = std::max(tile.x, maxX);
|
|
|
|
|
maxY = std::max(tile.y, maxY);
|
|
|
|
|
minX = std::min(tile.x, minX);
|
|
|
|
|
minY = std::min(tile.y, minY);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QRectF bounds((minX - 2) * tileSize, (minY - 2) * tileSize, (maxX - minX + 4) * tileSize, (maxY - minY + 4) * tileSize); //tiles start with 1, QRectF from 0
|
|
|
|
|
redraw({bounds});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AbstractViewportLayer::redraw(const std::set<CGObjectInstance *> & objects)
|
2022-09-18 03:23:17 +04:00
|
|
|
{
|
2025-10-06 20:33:09 +02:00
|
|
|
std::vector<QRectF> areas(objects.size());
|
|
|
|
|
for (const CGObjectInstance * object : objects)
|
|
|
|
|
{
|
|
|
|
|
areas.push_back(getObjectArea(object));
|
|
|
|
|
}
|
|
|
|
|
redraw(areas);
|
2022-09-18 03:23:17 +04:00
|
|
|
}
|
|
|
|
|
|
2025-10-06 20:33:09 +02:00
|
|
|
void AbstractViewportLayer::redraw(const std::vector<QRectF> & areas)
|
|
|
|
|
{
|
|
|
|
|
std::set<QGraphicsItem *> intersectingSectors;
|
|
|
|
|
for (QGraphicsItem * existingSector : getAllSectors())
|
|
|
|
|
{
|
|
|
|
|
for (auto area : areas)
|
|
|
|
|
{
|
|
|
|
|
if (existingSector->sceneBoundingRect().intersects(area))
|
|
|
|
|
{
|
|
|
|
|
intersectingSectors.insert(existingSector);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
redrawSectors(intersectingSectors);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QRectF AbstractViewportLayer::getObjectArea(const CGObjectInstance * object)
|
|
|
|
|
{
|
|
|
|
|
auto pos = object->pos;
|
|
|
|
|
int x = ((pos.x + 1) * tileSize) - (object->getWidth() * tileSize); //Qt set 0,0 point on the top right corner, CGObjectInstance on the bottom left
|
|
|
|
|
int y = ((pos.y + 1) * tileSize) - (object->getHeight() * tileSize);
|
|
|
|
|
QRectF objectArea(x, y, object->getWidth() * tileSize, object->getHeight() * tileSize);
|
|
|
|
|
return objectArea;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AbstractViewportLayer::addSector(QGraphicsItem * sector)
|
|
|
|
|
{
|
|
|
|
|
items->addToGroup(sector);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AbstractViewportLayer::removeSector(QGraphicsItem * sector)
|
|
|
|
|
{
|
|
|
|
|
items->removeFromGroup(sector);
|
|
|
|
|
delete sector;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AbstractViewportLayer::redrawSectors(std::set<QGraphicsItem *> & sectors)
|
|
|
|
|
{
|
|
|
|
|
std::set<QGraphicsItem *> sectorsToRemove;
|
|
|
|
|
|
|
|
|
|
for (QGraphicsItem * existingSectors : getAllSectors())
|
|
|
|
|
{
|
|
|
|
|
for (QGraphicsItem * sector : sectors)
|
|
|
|
|
{
|
|
|
|
|
if (existingSectors->sceneBoundingRect().contains(sector->sceneBoundingRect()))
|
|
|
|
|
sectorsToRemove.insert(existingSectors);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for (QGraphicsItem * sectorToRemove : sectorsToRemove)
|
|
|
|
|
{
|
|
|
|
|
addSector(draw(sectorToRemove->sceneBoundingRect()));
|
|
|
|
|
removeSector(sectorToRemove);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const QList<QGraphicsItem *> AbstractViewportLayer::getAllSectors() //returning const is necessary to avoid "range-loop might detach Qt container" problem
|
|
|
|
|
{
|
|
|
|
|
QList<QGraphicsItem *> emptyList;
|
|
|
|
|
return items ? items->childItems() : emptyList;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::set<QGraphicsItem *> AbstractViewportLayer::getContainingSectors(const std::vector<int3> & tiles)
|
|
|
|
|
{
|
|
|
|
|
std::set<QGraphicsItem *> result;
|
|
|
|
|
for (QGraphicsItem * existingSector : getAllSectors()) {
|
|
|
|
|
for (const int3 tile : tiles)
|
|
|
|
|
{
|
|
|
|
|
if (existingSector->sceneBoundingRect().contains(QPointF(tile.x * tileSize, tile.y * tileSize)))
|
|
|
|
|
{
|
|
|
|
|
result.insert(existingSector);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::set<QGraphicsItem *> AbstractViewportLayer::getIntersectingSectors(const std::vector<QRectF> & areas)
|
|
|
|
|
{
|
|
|
|
|
std::set<QGraphicsItem *> result;
|
|
|
|
|
for (QGraphicsItem * existingSector : getAllSectors()) {
|
|
|
|
|
for (QRectF area : areas)
|
|
|
|
|
{
|
|
|
|
|
if (existingSector->sceneBoundingRect().intersects(area))
|
|
|
|
|
{
|
|
|
|
|
result.insert(existingSector);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
EmptyLayer::EmptyLayer(MapSceneBase * s): AbstractFixedLayer(s)
|
|
|
|
|
{
|
|
|
|
|
isShown = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void EmptyLayer::update()
|
2022-09-18 03:23:17 +04:00
|
|
|
{
|
|
|
|
|
if(!map)
|
|
|
|
|
return;
|
2025-10-06 20:33:09 +02:00
|
|
|
|
|
|
|
|
pixmap = std::make_unique<QPixmap>(map->width * 32, map->height * 32);
|
|
|
|
|
redraw();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GridLayer::GridLayer(MapSceneBase * s): AbstractViewportLayer(s)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QGraphicsItem * GridLayer::draw(const QRectF & section)
|
|
|
|
|
{
|
|
|
|
|
QPixmap pixmap(toInt(section.width()), toInt(section.height()));
|
|
|
|
|
pixmap.fill(Qt::transparent);
|
|
|
|
|
if (isShown)
|
2022-09-18 03:23:17 +04:00
|
|
|
{
|
2025-10-06 20:33:09 +02:00
|
|
|
QPainter painter(&pixmap);
|
|
|
|
|
painter.setPen(QColor(0, 0, 0, 190));
|
|
|
|
|
|
|
|
|
|
for(int j = 0; j <= pixmap.height(); j += tileSize)
|
2022-09-18 03:23:17 +04:00
|
|
|
{
|
2025-10-06 20:33:09 +02:00
|
|
|
painter.drawLine(0, j, pixmap.width(), j);
|
|
|
|
|
}
|
|
|
|
|
for(int i = 0; i <= pixmap.width(); i += tileSize)
|
|
|
|
|
{
|
|
|
|
|
painter.drawLine(i, 0, i, pixmap.height());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QGraphicsItem * result = scene->addPixmap(pixmap);
|
|
|
|
|
result->setPos(section.x(), section.y());
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PassabilityLayer::PassabilityLayer(MapSceneBase * s): AbstractViewportLayer(s)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QGraphicsItem * PassabilityLayer::draw(const QRectF & section)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
QPixmap pixmap(toInt(section.width()), toInt(section.height()));
|
|
|
|
|
pixmap.fill(Qt::transparent);
|
|
|
|
|
|
|
|
|
|
if(isShown)
|
|
|
|
|
{
|
|
|
|
|
QPainter painter(&pixmap);
|
|
|
|
|
for(int j = 0; j <= pixmap.height(); j += tileSize)
|
|
|
|
|
{
|
|
|
|
|
for(int i = 0; i < pixmap.width(); i += tileSize)
|
2022-09-18 03:23:17 +04:00
|
|
|
{
|
2025-10-06 20:33:09 +02:00
|
|
|
auto tl = map->getTile(int3(toInt(section.x())/tileSize + i/tileSize, toInt(section.y())/tileSize + j/tileSize, scene->level));
|
|
|
|
|
if(tl.blocked() || tl.visitable())
|
|
|
|
|
{
|
|
|
|
|
painter.fillRect(i, j, 31, 31, tl.visitable() ? QColor(200, 200, 0, 64) : QColor(255, 0, 0, 64));
|
|
|
|
|
}
|
2022-09-18 03:23:17 +04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-10-06 20:33:09 +02:00
|
|
|
|
|
|
|
|
QGraphicsItem * result = scene->addPixmap(pixmap);
|
|
|
|
|
result->setPos(section.x(), section.y());
|
|
|
|
|
|
|
|
|
|
return result;
|
2022-09-18 03:23:17 +04:00
|
|
|
}
|
|
|
|
|
|
2025-10-06 20:33:09 +02:00
|
|
|
ObjectPickerLayer::ObjectPickerLayer(MapSceneBase * s): AbstractViewportLayer(s)
|
2023-09-11 18:01:53 +02:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-06 20:33:09 +02:00
|
|
|
void ObjectPickerLayer::highlight(const std::function<bool(const CGObjectInstance *)> & predicate)
|
2023-09-11 18:01:53 +02:00
|
|
|
{
|
|
|
|
|
if(!map)
|
|
|
|
|
return;
|
|
|
|
|
|
2025-08-02 02:33:47 +02:00
|
|
|
for(int j = 0; j < map->height; ++j)
|
2023-09-11 18:01:53 +02:00
|
|
|
{
|
2025-08-02 02:33:47 +02:00
|
|
|
for(int i = 0; i < map->width; ++i)
|
2023-09-11 18:01:53 +02:00
|
|
|
{
|
2025-08-02 02:33:47 +02:00
|
|
|
auto tl = map->getTile(int3(i, j, scene->level));
|
|
|
|
|
ObjectInstanceID objID = tl.topVisitableObj();
|
|
|
|
|
if(!objID.hasValue() && !tl.blockingObjects.empty())
|
|
|
|
|
objID = tl.blockingObjects.front();
|
2025-03-19 14:40:45 +00:00
|
|
|
|
2025-08-02 02:33:47 +02:00
|
|
|
if (objID.hasValue())
|
|
|
|
|
{
|
|
|
|
|
const CGObjectInstance * obj = map->getObject(objID);
|
|
|
|
|
|
|
|
|
|
if(obj && predicate(obj))
|
|
|
|
|
possibleObjects.insert(obj);
|
2023-09-11 18:44:55 +02:00
|
|
|
}
|
2023-09-11 18:01:53 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
isActive = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool ObjectPickerLayer::isVisible() const
|
|
|
|
|
{
|
|
|
|
|
return isShown && isActive;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ObjectPickerLayer::clear()
|
|
|
|
|
{
|
|
|
|
|
possibleObjects.clear();
|
|
|
|
|
isActive = false;
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-06 20:33:09 +02:00
|
|
|
QGraphicsItem * ObjectPickerLayer::draw(const QRectF & section)
|
2023-09-11 18:01:53 +02:00
|
|
|
{
|
2025-10-06 20:33:09 +02:00
|
|
|
|
|
|
|
|
int offsetX = toInt(section.x());
|
|
|
|
|
int offsetY = toInt(section.y());
|
|
|
|
|
QPixmap pixmap(toInt(section.width()), toInt(section.height()));
|
|
|
|
|
pixmap.fill(Qt::transparent);
|
|
|
|
|
|
|
|
|
|
if(isVisible())
|
|
|
|
|
pixmap.fill(QColor(255, 255, 255, 128));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
QPainter painter(&pixmap);
|
2023-09-11 18:01:53 +02:00
|
|
|
painter.setCompositionMode(QPainter::CompositionMode_Source);
|
2025-10-06 20:33:09 +02:00
|
|
|
for(const auto * obj : possibleObjects)
|
2023-09-11 18:01:53 +02:00
|
|
|
{
|
|
|
|
|
if(obj->pos.z != scene->level)
|
|
|
|
|
continue;
|
2025-10-06 20:33:09 +02:00
|
|
|
|
|
|
|
|
for(const auto & pos : obj->getBlockedPos())
|
|
|
|
|
painter.fillRect(pos.x * tileSize - offsetX, pos.y * tileSize - offsetY, tileSize, tileSize, QColor(255, 211, 0, 64));
|
2023-09-11 18:01:53 +02:00
|
|
|
}
|
2025-10-06 20:33:09 +02:00
|
|
|
|
|
|
|
|
QGraphicsItem * result = scene->addPixmap(pixmap);
|
|
|
|
|
result->setPos(section.x(), section.y());
|
|
|
|
|
|
|
|
|
|
return result;
|
2023-09-11 18:01:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ObjectPickerLayer::select(const CGObjectInstance * obj)
|
|
|
|
|
{
|
|
|
|
|
if(obj && possibleObjects.count(obj))
|
|
|
|
|
{
|
|
|
|
|
clear();
|
2025-10-06 20:33:09 +02:00
|
|
|
Q_EMIT selectionMade(obj);
|
2023-09-11 18:01:53 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ObjectPickerLayer::discard()
|
|
|
|
|
{
|
|
|
|
|
clear();
|
2025-10-06 20:33:09 +02:00
|
|
|
Q_EMIT selectionMade(nullptr);
|
2023-09-11 18:01:53 +02:00
|
|
|
}
|
|
|
|
|
|
2025-10-06 20:33:09 +02:00
|
|
|
SelectionTerrainLayer::SelectionTerrainLayer(MapSceneBase * s): AbstractViewportLayer(s)
|
2022-09-18 03:23:17 +04:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-06 20:33:09 +02:00
|
|
|
QGraphicsItem * SelectionTerrainLayer::draw(const QRectF & section)
|
2022-09-18 03:23:17 +04:00
|
|
|
{
|
2025-10-06 20:33:09 +02:00
|
|
|
int offsetX = toInt(section.x());
|
|
|
|
|
int offsetY = toInt(section.y());
|
|
|
|
|
QPixmap pixmap(toInt(section.width()), toInt(section.height()));
|
|
|
|
|
pixmap.fill(Qt::transparent);
|
|
|
|
|
|
|
|
|
|
QPainter painter(&pixmap);
|
2022-09-18 03:23:17 +04:00
|
|
|
|
|
|
|
|
painter.setCompositionMode(QPainter::CompositionMode_Source);
|
2025-10-06 20:33:09 +02:00
|
|
|
for(const auto & t : area)
|
2022-09-18 03:23:17 +04:00
|
|
|
{
|
2025-10-06 20:33:09 +02:00
|
|
|
if(section.contains(t.x * tileSize, t.y * tileSize))
|
|
|
|
|
painter.fillRect(t.x * tileSize - offsetX, t.y * tileSize - offsetY, 31, 31, QColor(128, 128, 128, 96));
|
2022-09-18 03:23:17 +04:00
|
|
|
}
|
2025-10-06 20:33:09 +02:00
|
|
|
|
|
|
|
|
QGraphicsPixmapItem * result = scene->addPixmap(pixmap);
|
|
|
|
|
result->setPos(section.x(), section.y());
|
|
|
|
|
|
|
|
|
|
return result;
|
2022-09-18 03:23:17 +04:00
|
|
|
}
|
|
|
|
|
|
2025-10-06 20:33:09 +02:00
|
|
|
void SelectionTerrainLayer::select(const std::vector<int3> & tiles)
|
2022-09-18 03:23:17 +04:00
|
|
|
{
|
2025-10-06 20:33:09 +02:00
|
|
|
for (int3 tile : tiles)
|
2022-09-18 03:23:17 +04:00
|
|
|
{
|
2025-10-06 20:33:09 +02:00
|
|
|
if(!area.count(tile))
|
|
|
|
|
{
|
|
|
|
|
area.insert(tile);
|
|
|
|
|
}
|
2022-09-18 03:23:17 +04:00
|
|
|
}
|
2025-10-06 20:33:09 +02:00
|
|
|
redraw(tiles);
|
2022-09-18 03:23:17 +04:00
|
|
|
onSelection();
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-06 20:33:09 +02:00
|
|
|
void SelectionTerrainLayer::erase(const std::vector<int3> & tiles)
|
2022-09-18 03:23:17 +04:00
|
|
|
{
|
2025-10-06 20:33:09 +02:00
|
|
|
for (int3 tile : tiles)
|
2022-09-18 03:23:17 +04:00
|
|
|
{
|
2025-10-06 20:33:09 +02:00
|
|
|
if(area.count(tile))
|
|
|
|
|
{
|
|
|
|
|
area.erase(tile);
|
|
|
|
|
}
|
2022-09-18 03:23:17 +04:00
|
|
|
}
|
2025-10-06 20:33:09 +02:00
|
|
|
redraw(tiles);
|
2022-09-18 03:23:17 +04:00
|
|
|
onSelection();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SelectionTerrainLayer::clear()
|
|
|
|
|
{
|
|
|
|
|
area.clear();
|
|
|
|
|
onSelection();
|
2025-10-06 20:33:09 +02:00
|
|
|
redraw();
|
2022-09-18 03:23:17 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const std::set<int3> & SelectionTerrainLayer::selection() const
|
|
|
|
|
{
|
|
|
|
|
return area;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SelectionTerrainLayer::onSelection()
|
|
|
|
|
{
|
2025-10-06 20:33:09 +02:00
|
|
|
Q_EMIT selectionMade(!area.empty());
|
2022-09-18 03:23:17 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2025-10-06 20:33:09 +02:00
|
|
|
TerrainLayer::TerrainLayer(MapSceneBase * s): AbstractViewportLayer(s)
|
2022-09-18 03:23:17 +04:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-06 20:33:09 +02:00
|
|
|
void TerrainLayer::redrawTerrain(const std::vector<int3> & tiles)
|
2022-09-18 03:23:17 +04:00
|
|
|
{
|
2025-10-06 20:33:09 +02:00
|
|
|
redrawWithSurroundingTiles(tiles);
|
2022-09-18 03:23:17 +04:00
|
|
|
}
|
|
|
|
|
|
2025-10-06 20:33:09 +02:00
|
|
|
QGraphicsItem * TerrainLayer::draw(const QRectF & section)
|
2022-09-18 03:23:17 +04:00
|
|
|
{
|
2025-10-06 20:33:09 +02:00
|
|
|
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);
|
2022-09-18 03:23:17 +04:00
|
|
|
|
2025-10-06 20:33:09 +02:00
|
|
|
QPainter painter(&pixmap);
|
|
|
|
|
|
|
|
|
|
QPointF offset = section.topLeft();
|
|
|
|
|
|
|
|
|
|
for(int x = left/tileSize; x < right/tileSize; ++x)
|
2022-09-18 03:23:17 +04:00
|
|
|
{
|
2025-10-06 20:33:09 +02:00
|
|
|
for(int y = top/tileSize; y < bottom/tileSize; ++y)
|
2022-09-18 03:23:17 +04:00
|
|
|
{
|
2025-10-06 20:33:09 +02:00
|
|
|
handler->drawTerrainTile(painter, x, y, scene->level, offset);
|
|
|
|
|
handler->drawRiver(painter, x, y, scene->level, offset);
|
|
|
|
|
handler->drawRoad(painter, x, y, scene->level, offset);
|
2022-09-18 03:23:17 +04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-06 20:33:09 +02:00
|
|
|
QGraphicsPixmapItem * result = scene->addPixmap(pixmap);
|
|
|
|
|
result->setPos(section.x(), section.y());
|
|
|
|
|
|
|
|
|
|
return result;
|
2022-09-18 03:23:17 +04:00
|
|
|
}
|
|
|
|
|
|
2025-10-06 20:33:09 +02:00
|
|
|
ObjectsLayer::ObjectsLayer(MapSceneBase * s): AbstractViewportLayer(s)
|
2022-09-18 03:23:17 +04:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-06 20:33:09 +02:00
|
|
|
QGraphicsItem * ObjectsLayer::draw(const QRectF & section)
|
2022-09-18 03:23:17 +04:00
|
|
|
{
|
2025-10-06 20:33:09 +02:00
|
|
|
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);
|
2023-10-13 05:21:09 +02:00
|
|
|
|
2025-10-06 20:33:09 +02:00
|
|
|
if (isShown)
|
2022-09-18 03:23:17 +04:00
|
|
|
{
|
2025-10-06 20:33:09 +02:00
|
|
|
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)
|
2022-09-18 03:23:17 +04:00
|
|
|
{
|
2025-10-06 20:33:09 +02:00
|
|
|
for(int y = (top - margin)/tileSize; y < (bottom + margin)/tileSize; ++y)
|
2022-12-03 23:11:40 +04:00
|
|
|
{
|
2025-10-06 20:33:09 +02:00
|
|
|
handler->drawObjects(painter, x, y, scene->level, offset, lockedObjects);
|
2022-12-03 23:11:40 +04:00
|
|
|
}
|
2022-09-18 03:23:17 +04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-06 20:33:09 +02:00
|
|
|
QGraphicsPixmapItem * result = scene->addPixmap(pixmap);
|
|
|
|
|
result->setPos(section.x(), section.y());
|
|
|
|
|
|
|
|
|
|
return result;
|
2022-09-18 03:23:17 +04:00
|
|
|
}
|
|
|
|
|
|
2025-10-06 20:33:09 +02:00
|
|
|
void ObjectsLayer::redrawObjects(const std::set<CGObjectInstance *> & objects)
|
2022-09-18 03:23:17 +04:00
|
|
|
{
|
2025-10-06 20:33:09 +02:00
|
|
|
redraw(objects);
|
2022-09-18 03:23:17 +04:00
|
|
|
}
|
|
|
|
|
|
2023-10-13 05:21:09 +02:00
|
|
|
void ObjectsLayer::setLockObject(const CGObjectInstance * object, bool lock)
|
|
|
|
|
{
|
|
|
|
|
if(lock)
|
|
|
|
|
lockedObjects.insert(object);
|
|
|
|
|
else
|
|
|
|
|
lockedObjects.erase(object);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ObjectsLayer::unlockAll()
|
|
|
|
|
{
|
|
|
|
|
lockedObjects.clear();
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-06 20:33:09 +02:00
|
|
|
SelectionObjectsLayer::SelectionObjectsLayer(MapSceneBase * s): AbstractViewportLayer(s), newObject(nullptr)
|
2022-09-18 03:23:17 +04:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2025-10-06 20:33:09 +02:00
|
|
|
QGraphicsItem * SelectionObjectsLayer::draw(const QRectF & section)
|
2022-09-18 03:23:17 +04:00
|
|
|
{
|
2025-10-06 20:33:09 +02:00
|
|
|
QPixmap pixmap(toInt(section.width()), toInt(section.height()));
|
|
|
|
|
pixmap.fill(Qt::transparent);
|
|
|
|
|
|
|
|
|
|
if (isShown)
|
2022-09-18 03:23:17 +04:00
|
|
|
{
|
2025-10-06 20:33:09 +02:00
|
|
|
QPainter painter(&pixmap);
|
|
|
|
|
painter.setCompositionMode(QPainter::CompositionMode_Source);
|
|
|
|
|
painter.setPen(Qt::white);
|
|
|
|
|
|
|
|
|
|
QPointF offset = section.topLeft();
|
|
|
|
|
|
|
|
|
|
for(auto * obj : selectedObjects)
|
2022-09-18 03:23:17 +04:00
|
|
|
{
|
2025-10-06 20:33:09 +02:00
|
|
|
auto objectArea = getObjectArea(obj);
|
|
|
|
|
if(obj != newObject.get() && section.intersects(objectArea))
|
2022-09-18 03:23:17 +04:00
|
|
|
{
|
2025-10-06 20:33:09 +02:00
|
|
|
auto pos = obj->anchorPos();
|
|
|
|
|
QRectF bbox(pos.x, pos.y, 1, 1);
|
|
|
|
|
for(const auto & t : obj->getBlockedPos())
|
|
|
|
|
{
|
|
|
|
|
QPointF topLeft(std::min(t.x * 1.0, bbox.topLeft().x()), std::min(t.y * 1.0, bbox.topLeft().y()));
|
|
|
|
|
bbox.setTopLeft(topLeft);
|
|
|
|
|
QPointF bottomRight(std::max(t.x * 1.0, bbox.bottomRight().x()), std::max(t.y * 1.0, bbox.bottomRight().y()));
|
|
|
|
|
bbox.setBottomRight(bottomRight);
|
|
|
|
|
}
|
|
|
|
|
//selection box's size was decreased by 1 px to get rid of a persistent bug
|
|
|
|
|
//with displaying a box on a border of two sectors. Bite me.
|
|
|
|
|
|
|
|
|
|
painter.setOpacity(1.0);
|
|
|
|
|
QRectF rect((bbox.x() * tileSize + 1) - offset.x(), (bbox.y() * tileSize + 1) - offset.y(), (bbox.width() * tileSize) - 2, (bbox.height() * tileSize) - 2);
|
|
|
|
|
painter.drawRect(rect);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(selectionMode == SelectionMode::MOVEMENT && (shift.x() || shift.y()))
|
|
|
|
|
{
|
|
|
|
|
objectArea.moveTo(objectArea.topLeft() + (shift * tileSize));
|
|
|
|
|
if (section.intersects(objectArea))
|
|
|
|
|
{
|
|
|
|
|
painter.setOpacity(0.7);
|
|
|
|
|
auto newPos = QPoint(obj->anchorPos().x, obj->anchorPos().y) + shift;
|
|
|
|
|
handler->drawObjectAt(painter, obj, newPos.x(), newPos.y(), offset);
|
|
|
|
|
}
|
2022-09-18 03:23:17 +04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-10-06 20:33:09 +02:00
|
|
|
|
|
|
|
|
QGraphicsPixmapItem * result = scene->addPixmap(pixmap);
|
|
|
|
|
result->setPos(section.x(), section.y());
|
|
|
|
|
|
|
|
|
|
return result;
|
2022-09-18 03:23:17 +04:00
|
|
|
}
|
|
|
|
|
|
2022-12-05 01:32:50 +04:00
|
|
|
CGObjectInstance * SelectionObjectsLayer::selectObjectAt(int x, int y, const CGObjectInstance * ignore) const
|
2022-09-18 03:23:17 +04:00
|
|
|
{
|
|
|
|
|
if(!map || !map->isInTheMap(int3(x, y, scene->level)))
|
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
|
|
auto & objects = handler->getObjects(x, y, scene->level);
|
|
|
|
|
|
|
|
|
|
//visitable is most important
|
|
|
|
|
for(auto & object : objects)
|
|
|
|
|
{
|
2023-10-13 05:21:09 +02:00
|
|
|
if(!object.obj || object.obj == ignore || lockedObjects.count(object.obj))
|
2022-09-18 03:23:17 +04:00
|
|
|
continue;
|
|
|
|
|
|
2024-10-02 16:40:06 +00:00
|
|
|
if(object.obj->visitableAt(int3(x, y, scene->level)))
|
2022-09-18 03:23:17 +04:00
|
|
|
{
|
2023-10-20 01:25:06 +02:00
|
|
|
return const_cast<CGObjectInstance*>(object.obj);
|
2022-09-18 03:23:17 +04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//if not visitable tile - try to get blocked
|
|
|
|
|
for(auto & object : objects)
|
|
|
|
|
{
|
2023-10-13 05:21:09 +02:00
|
|
|
if(!object.obj || object.obj == ignore || lockedObjects.count(object.obj))
|
2022-09-18 03:23:17 +04:00
|
|
|
continue;
|
|
|
|
|
|
2024-10-02 16:40:06 +00:00
|
|
|
if(object.obj->blockingAt(int3(x, y, scene->level)))
|
2022-09-18 03:23:17 +04:00
|
|
|
{
|
2023-10-20 01:25:06 +02:00
|
|
|
return const_cast<CGObjectInstance*>(object.obj);
|
2022-09-18 03:23:17 +04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//finally, we can take any object
|
|
|
|
|
for(auto & object : objects)
|
|
|
|
|
{
|
2023-10-13 05:21:09 +02:00
|
|
|
if(!object.obj || object.obj == ignore || lockedObjects.count(object.obj))
|
2022-09-18 03:23:17 +04:00
|
|
|
continue;
|
|
|
|
|
|
2024-10-02 16:40:06 +00:00
|
|
|
if(object.obj->coveringAt(int3(x, y, scene->level)))
|
2022-09-18 03:23:17 +04:00
|
|
|
{
|
2023-10-20 01:25:06 +02:00
|
|
|
return const_cast<CGObjectInstance*>(object.obj);
|
2022-09-18 03:23:17 +04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SelectionObjectsLayer::selectObjects(int x1, int y1, int x2, int y2)
|
|
|
|
|
{
|
|
|
|
|
if(!map)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if(x1 > x2)
|
|
|
|
|
std::swap(x1, x2);
|
|
|
|
|
|
|
|
|
|
if(y1 > y2)
|
|
|
|
|
std::swap(y1, y2);
|
2025-10-06 20:33:09 +02:00
|
|
|
|
|
|
|
|
std::set<CGObjectInstance *> selectedObjects;
|
2022-09-18 03:23:17 +04:00
|
|
|
for(int j = y1; j < y2; ++j)
|
|
|
|
|
{
|
|
|
|
|
for(int i = x1; i < x2; ++i)
|
|
|
|
|
{
|
2022-12-04 16:57:46 +04:00
|
|
|
if(map->isInTheMap(int3(i, j, scene->level)))
|
|
|
|
|
{
|
|
|
|
|
for(auto & o : handler->getObjects(i, j, scene->level))
|
2023-10-13 05:21:09 +02:00
|
|
|
if(!lockedObjects.count(o.obj))
|
2025-10-06 20:33:09 +02:00
|
|
|
{
|
|
|
|
|
selectedObjects.insert(const_cast<CGObjectInstance*>(o.obj));
|
|
|
|
|
}
|
2022-12-04 16:57:46 +04:00
|
|
|
}
|
2022-09-18 03:23:17 +04:00
|
|
|
}
|
|
|
|
|
}
|
2025-10-06 20:33:09 +02:00
|
|
|
selectObjects(selectedObjects);
|
2022-09-18 03:23:17 +04:00
|
|
|
}
|
|
|
|
|
|
2025-10-06 20:33:09 +02:00
|
|
|
void SelectionObjectsLayer::selectObject(CGObjectInstance * obj)
|
2022-09-18 03:23:17 +04:00
|
|
|
{
|
|
|
|
|
selectedObjects.insert(obj);
|
2025-10-06 20:33:09 +02:00
|
|
|
onSelection();
|
|
|
|
|
redraw({obj});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SelectionObjectsLayer::selectObjects(const std::set<CGObjectInstance *> & objs)
|
|
|
|
|
{
|
|
|
|
|
for (CGObjectInstance * obj : objs)
|
2022-09-18 03:23:17 +04:00
|
|
|
{
|
2025-10-06 20:33:09 +02:00
|
|
|
selectedObjects.insert(obj);
|
2022-09-18 03:23:17 +04:00
|
|
|
}
|
2025-10-06 20:33:09 +02:00
|
|
|
onSelection();
|
|
|
|
|
redraw(objs);
|
2022-09-18 03:23:17 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SelectionObjectsLayer::deselectObject(CGObjectInstance * obj)
|
|
|
|
|
{
|
|
|
|
|
selectedObjects.erase(obj);
|
2025-10-06 20:33:09 +02:00
|
|
|
redraw({obj});
|
2022-09-18 03:23:17 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool SelectionObjectsLayer::isSelected(const CGObjectInstance * obj) const
|
|
|
|
|
{
|
|
|
|
|
return selectedObjects.count(const_cast<CGObjectInstance*>(obj));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::set<CGObjectInstance*> SelectionObjectsLayer::getSelection() const
|
|
|
|
|
{
|
|
|
|
|
return selectedObjects;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SelectionObjectsLayer::clear()
|
|
|
|
|
{
|
|
|
|
|
selectedObjects.clear();
|
|
|
|
|
shift.setX(0);
|
|
|
|
|
shift.setY(0);
|
2025-10-06 20:33:09 +02:00
|
|
|
redraw();
|
2022-09-18 03:23:17 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SelectionObjectsLayer::onSelection()
|
|
|
|
|
{
|
2025-10-06 20:33:09 +02:00
|
|
|
Q_EMIT selectionMade(!selectedObjects.empty());
|
2022-09-18 03:23:17 +04:00
|
|
|
}
|
|
|
|
|
|
2025-10-06 20:33:09 +02:00
|
|
|
void SelectionObjectsLayer::setShift(int x, int y)
|
|
|
|
|
{
|
|
|
|
|
std::vector<QRectF>areas;
|
|
|
|
|
|
|
|
|
|
if(shift.x() || shift.y())
|
|
|
|
|
{
|
|
|
|
|
for (auto * selectedObject : selectedObjects)
|
|
|
|
|
{
|
|
|
|
|
QRectF formerArea = getObjectArea(selectedObject);
|
|
|
|
|
formerArea.moveTo(formerArea.topLeft() + (shift * tileSize));
|
|
|
|
|
areas.emplace_back(formerArea);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
shift = QPoint(x, y);
|
|
|
|
|
for (auto * selectedObject : selectedObjects)
|
|
|
|
|
{
|
|
|
|
|
QRectF area = getObjectArea(selectedObject);
|
|
|
|
|
area.moveTo(area.topLeft() + (shift * tileSize));
|
|
|
|
|
areas.emplace_back(area);
|
|
|
|
|
}
|
|
|
|
|
redraw(areas);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SelectionObjectsLayer::setLockObject(CGObjectInstance * object, bool lock)
|
2023-10-13 05:21:09 +02:00
|
|
|
{
|
|
|
|
|
if(lock)
|
|
|
|
|
lockedObjects.insert(object);
|
|
|
|
|
else
|
|
|
|
|
lockedObjects.erase(object);
|
2025-10-06 20:33:09 +02:00
|
|
|
redraw({object});
|
2023-10-13 05:21:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SelectionObjectsLayer::unlockAll()
|
|
|
|
|
{
|
|
|
|
|
lockedObjects.clear();
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-06 20:33:09 +02:00
|
|
|
MinimapLayer::MinimapLayer(MapSceneBase * s): AbstractFixedLayer(s)
|
2022-09-18 03:23:17 +04:00
|
|
|
{
|
2025-10-06 20:33:09 +02:00
|
|
|
|
2022-09-18 03:23:17 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MinimapLayer::update()
|
|
|
|
|
{
|
|
|
|
|
if(!map)
|
|
|
|
|
return;
|
2025-10-06 20:33:09 +02:00
|
|
|
|
|
|
|
|
pixmap = std::make_unique<QPixmap>(map->width, map->height);
|
|
|
|
|
|
2022-09-18 03:23:17 +04:00
|
|
|
QPainter painter(pixmap.get());
|
2024-06-24 03:23:26 +02:00
|
|
|
//coordinate transformation
|
2022-09-18 03:23:17 +04:00
|
|
|
for(int j = 0; j < map->height; ++j)
|
|
|
|
|
{
|
|
|
|
|
for(int i = 0; i < map->width; ++i)
|
|
|
|
|
{
|
|
|
|
|
handler->drawMinimapTile(painter, i, j, scene->level);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
redraw();
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-06 20:33:09 +02:00
|
|
|
MinimapViewLayer::MinimapViewLayer(MapSceneBase * s): AbstractFixedLayer(s)
|
2022-09-18 03:23:17 +04:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MinimapViewLayer::update()
|
|
|
|
|
{
|
|
|
|
|
if(!map)
|
|
|
|
|
return;
|
2025-10-06 20:33:09 +02:00
|
|
|
|
|
|
|
|
pixmap = std::make_unique<QPixmap>(map->width, map->height);
|
|
|
|
|
|
2022-10-13 01:40:52 +04:00
|
|
|
draw();
|
2022-09-18 03:23:17 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MinimapViewLayer::draw()
|
|
|
|
|
{
|
|
|
|
|
if(!map)
|
|
|
|
|
return;
|
|
|
|
|
|
2022-10-13 01:58:49 +04:00
|
|
|
pixmap->fill(Qt::transparent);
|
2022-09-18 03:23:17 +04:00
|
|
|
|
|
|
|
|
//maybe not optimal but ok
|
|
|
|
|
QPainter painter(pixmap.get());
|
2022-10-13 01:58:49 +04:00
|
|
|
painter.setPen(Qt::white);
|
2022-09-18 03:23:17 +04:00
|
|
|
painter.drawRect(x, y, w, h);
|
|
|
|
|
|
|
|
|
|
redraw();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MinimapViewLayer::setViewport(int _x, int _y, int _w, int _h)
|
|
|
|
|
{
|
|
|
|
|
x = _x;
|
|
|
|
|
y = _y;
|
|
|
|
|
w = _w;
|
|
|
|
|
h = _h;
|
|
|
|
|
draw();
|
|
|
|
|
}
|