Browse Source

Merge pull request #6230 from Opuszek/fix_editor_display_blocking_of_objects

Rework drawing objects and fix drawing locked objects
Ivan Savenko 1 ngày trước cách đây
mục cha
commit
4ffd1b6309
3 tập tin đã thay đổi với 39 bổ sung52 xóa
  1. 33 34
      mapeditor/maphandler.cpp
  2. 2 2
      mapeditor/maphandler.h
  3. 4 16
      mapeditor/scenelayer.cpp

+ 33 - 34
mapeditor/maphandler.cpp

@@ -365,49 +365,39 @@ std::vector<ObjectRect> & 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<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::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))
-	{
-		const CGObjectInstance * obj = object.obj;
-		if(!obj)
-		{
-			logGlobal->error("Stray map object that isn't fading");
-			return;
-		}
 
-		uint8_t animationFrame = 0;
+	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;
 
-		auto objData = findObjectBitmap(obj, animationFrame, obj->ID == Obj::HERO ? 2 : 0);
-		if(obj->ID == Obj::HERO && obj->tempOwner.isValidPlayer())
-			objData.flagBitmap = findFlagBitmap(dynamic_cast<const CGHeroInstance*>(obj), 0, obj->tempOwner, 4);
-
-		if(objData.objBitmap)
+	for(int x = left; x < right; ++x)
+	{
+		for(int y = top; y < bottom; ++y)
 		{
-			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 & object : getObjects(x, y, z))
+				objectMap[object.obj->pos].insert(object.obj);
 		}
 	}
+
+	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);
 	}
 }
 

+ 2 - 2
mapeditor/maphandler.h

@@ -111,8 +111,8 @@ public:
 	std::set<int3> 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<const CGObjectInstance *> & 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<const CGObjectInstance *> & 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);
 

+ 4 - 16
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)