소스 검색

Redesign map editor rendering

nordsoft 2 년 전
부모
커밋
b9a660f6c3
7개의 변경된 파일148개의 추가작업 그리고 237개의 파일을 삭제
  1. 2 1
      lib/mapping/ObstacleProxy.cpp
  2. 2 2
      lib/mapping/ObstacleProxy.h
  3. 0 2
      mapeditor/mainwindow.cpp
  4. 8 8
      mapeditor/mapcontroller.cpp
  5. 108 194
      mapeditor/maphandler.cpp
  6. 24 26
      mapeditor/maphandler.h
  7. 4 4
      mapeditor/scenelayer.cpp

+ 2 - 1
lib/mapping/ObstacleProxy.cpp

@@ -208,10 +208,11 @@ bool EditorObstaclePlacer::isInTheMap(const int3& tile)
 	return map->isInTheMap(tile);
 }
 
-void EditorObstaclePlacer::placeObstacles(CRandomGenerator & rand)
+std::set<CGObjectInstance*> EditorObstaclePlacer::placeObstacles(CRandomGenerator & rand)
 {
 	auto obstacles = createObstacles(rand);
 	finalInsertion(map->getEditManager(), obstacles);
+	return obstacles;
 }
 
 VCMI_LIB_NAMESPACE_END

+ 2 - 2
lib/mapping/ObstacleProxy.h

@@ -67,10 +67,10 @@ public:
 
 	bool isInTheMap(const int3& tile) override;
 
-	void placeObstacles(CRandomGenerator& rand);
+	std::set<CGObjectInstance*> placeObstacles(CRandomGenerator& rand);
 
 private:
 	CMap* map;
 };
 
-VCMI_LIB_NAMESPACE_END
+VCMI_LIB_NAMESPACE_END

+ 0 - 2
mapeditor/mainwindow.cpp

@@ -1095,9 +1095,7 @@ void MainWindow::on_actionUpdate_appearance_triggered()
 				}
 				app = templates.front();
 			}
-			auto tiles = controller.mapHandler()->getTilesUnderObject(obj);
 			obj->appearance = app;
-			controller.mapHandler()->invalidate(tiles);
 			controller.mapHandler()->invalidate(obj);
 			controller.scene(mapLevel)->selectionObjectsView.deselectObject(obj);
 		}

+ 8 - 8
mapeditor/mapcontroller.cpp

@@ -350,10 +350,10 @@ void MapController::commitObjectErase(int level)
 		return;
 	}
 
-	for (auto obj : selectedObjects)
+	for (auto & obj : selectedObjects)
 	{
 		//invalidate tiles under objects
-		_mapHandler->invalidate(_mapHandler->getTilesUnderObject(obj));
+		_mapHandler->removeObject(obj);
 		_scenes[level]->objectsView.setDirty(obj);
 	}
 
@@ -454,14 +454,16 @@ void MapController::commitObstacleFill(int level)
 	
 	for(auto & sel : _obstaclePainters)
 	{
-		sel.second->placeObstacles(CRandomGenerator::getDefault());
+		for(auto * o : sel.second->placeObstacles(CRandomGenerator::getDefault()))
+		{
+			_mapHandler->invalidate(o);
+			_scenes[level]->objectsView.setDirty(o);
+		}
 	}
-
-	_mapHandler->invalidateObjects();
 	
 	_scenes[level]->selectionTerrainView.clear();
 	_scenes[level]->selectionTerrainView.draw();
-	_scenes[level]->objectsView.draw(false); //TODO: enable smart invalidation (setDirty)
+	_scenes[level]->objectsView.draw();
 	_scenes[level]->passabilityView.update();
 	
 	_miniscenes[level]->updateViews();
@@ -500,10 +502,8 @@ void MapController::commitObjectShift(int level)
 			pos.z = level;
 			pos.x += shift.x(); pos.y += shift.y();
 			
-			auto prevPositions = _mapHandler->getTilesUnderObject(obj);
 			_scenes[level]->objectsView.setDirty(obj); //set dirty before movement
 			_map->getEditManager()->moveObject(obj, pos);
-			_mapHandler->invalidate(prevPositions);
 			_mapHandler->invalidate(obj);
 		}
 	}

+ 108 - 194
mapeditor/maphandler.cpp

@@ -25,14 +25,14 @@
 
 const int tileSize = 32;
 
-static bool objectBlitOrderSorter(const TileObject & a, const TileObject & b)
+static bool objectBlitOrderSorter(const ObjectRect & a, const ObjectRect & b)
 {
 	return MapHandler::compareObjectBlitOrder(a.obj, b.obj);
 }
 
 int MapHandler::index(int x, int y, int z) const
 {
-	return z * (sizes.x * sizes.y) + y * sizes.x + x;
+	return z * (map->width * map->height) + y * map->width + x;
 }
 
 int MapHandler::index(const int3 & p) const
@@ -48,14 +48,7 @@ MapHandler::MapHandler()
 
 void MapHandler::reset(const CMap * Map)
 {
-	ttiles.clear();
 	map = Map;
-	
-	//sizes of terrain
-	sizes.x = map->width;
-	sizes.y = map->height;
-	sizes.z = map->twoLevel ? 2 : 1;
-	
 	initObjectRects();
 	logGlobal->info("\tMaking object rects");
 }
@@ -176,67 +169,101 @@ void setPlayerColor(QImage * sur, PlayerColor player)
 		logGlobal->warn("Warning, setPlayerColor called on not 8bpp surface!");
 }
 
-void MapHandler::initObjectRects()
+std::shared_ptr<QImage> MapHandler::getObjectImage(const CGObjectInstance * obj)
 {
-	ttiles.resize(sizes.x * sizes.y * sizes.z);
+	if(	!obj
+	   || (obj->ID==Obj::HERO && static_cast<const CGHeroInstance*>(obj)->inTownGarrison) //garrisoned hero
+	   || (obj->ID==Obj::BOAT && static_cast<const CGBoat*>(obj)->hero)) //boat with hero (hero graphics is used)
+	{
+		return nullptr;
+	}
 	
-	//initializing objects / rects
-	for(const CGObjectInstance * elem : map->objects)
+	std::shared_ptr<Animation> animation = graphics->getAnimation(obj);
+	
+	//no animation at all
+	if(!animation)
+		return nullptr;
+	
+	//empty animation
+	if(animation->size(0) == 0)
+		return nullptr;
+	
+	auto image = animation->getImage(0, obj->ID == Obj::HERO ? 2 : 0);
+	if(!image)
 	{
-		CGObjectInstance *obj = const_cast<CGObjectInstance *>(elem);
-		if(	!obj
-		   || (obj->ID==Obj::HERO && static_cast<const CGHeroInstance*>(obj)->inTownGarrison) //garrisoned hero
-		   || (obj->ID==Obj::BOAT && static_cast<const CGBoat*>(obj)->hero)) //boat with hero (hero graphics is used)
-		{
-			continue;
-		}
-		
-		std::shared_ptr<Animation> animation = graphics->getAnimation(obj);
-		
-		//no animation at all
-		if(!animation)
-			continue;
-		
-		//empty animation
-		if(animation->size(0) == 0)
-			continue;
-		
-		auto image = animation->getImage(0, obj->ID == Obj::HERO ? 2 : 0);
-		if(!image)
+		//workaround for prisons
+		image = animation->getImage(0, 0);
+	}
+	
+	return image;
+}
+
+std::set<int3> MapHandler::removeObject(const CGObjectInstance *object)
+{
+	std::set<int3> result = tilesCache[object];
+	for(auto & t : result)
+	{
+		auto & objects = getObjects(t);
+		for(auto iter = objects.begin(); iter != objects.end(); ++iter)
 		{
-			//workaround for prisons
-			image = animation->getImage(0, 0);
-			if(!image)
-				continue;
+			if(iter->obj == object)
+			{
+				objects.erase(iter);
+				break;
+			}
 		}
-			
-		
-		for(int fx=0; fx < obj->getWidth(); ++fx)
+	}
+	
+	tilesCache.erase(object);
+	return result;
+}
+
+std::set<int3> MapHandler::addObject(const CGObjectInstance * object)
+{
+	auto image = getObjectImage(object);
+	if(!image)
+		return std::set<int3>{};
+	
+	for(int fx = 0; fx < object->getWidth(); ++fx)
+	{
+		for(int fy = 0; fy < object->getHeight(); ++fy)
 		{
-			for(int fy=0; fy < obj->getHeight(); ++fy)
+			int3 currTile(object->pos.x - fx, object->pos.y - fy, object->pos.z);
+			QRect cr(image->width() - fx * tileSize - tileSize,
+					 image->height() - fy * tileSize - tileSize,
+					 tileSize,
+					 tileSize);
+							
+			if( map->isInTheMap(currTile) && // within map
+			   cr.x() + cr.width() > 0 &&    // image has data on this tile
+			   cr.y() + cr.height() > 0)
 			{
-				int3 currTile(obj->pos.x - fx, obj->pos.y - fy, obj->pos.z);
-				QRect cr(image->width() - fx * tileSize - tileSize,
-						 image->height() - fy * tileSize - tileSize,
-						 image->width(),
-						 image->height());
-				
-				TileObject toAdd(obj, cr);
-				
-				if( map->isInTheMap(currTile) && // within map
-				   cr.x() + cr.width() > 0 &&           // image has data on this tile
-				   cr.y() + cr.height() > 0)
-				{
-					ttiles[index(currTile)].push_back(toAdd);
-				}
+				getObjects(currTile).emplace_back(object, cr);
+				tilesCache[object].insert(currTile);
 			}
 		}
 	}
 	
-	for(auto & tt : ttiles)
+	return tilesCache[object];
+}
+
+void MapHandler::initObjectRects()
+{
+	tileObjects.clear();
+	tilesCache.clear();
+	if(!map)
+		return;
+	
+	tileObjects.resize(map->width * map->height * (map->twoLevel ? 2 : 1));
+	
+	//initializing objects / rects
+	for(const CGObjectInstance * elem : map->objects)
 	{
-		stable_sort(tt.begin(), tt.end(), objectBlitOrderSorter);
+		addObject(elem);
 	}
+	
+	for(auto & tt : tileObjects)
+		stable_sort(tt.begin(), tt.end(), objectBlitOrderSorter);
 }
 
 bool MapHandler::compareObjectBlitOrder(const CGObjectInstance * a, const CGObjectInstance * b)
@@ -265,13 +292,13 @@ bool MapHandler::compareObjectBlitOrder(const CGObjectInstance * a, const CGObje
 	return false;
 }
 
-TileObject::TileObject(CGObjectInstance * obj_, QRect rect_)
+ObjectRect::ObjectRect(const CGObjectInstance * obj_, QRect rect_)
 : obj(obj_),
 rect(rect_)
 {
 }
 
-TileObject::~TileObject()
+ObjectRect::~ObjectRect()
 {
 }
 
@@ -295,31 +322,36 @@ std::shared_ptr<QImage> MapHandler::findFlagBitmapInternal(std::shared_ptr<Anima
 		return animation->getImage((anim / 4) % groupSize, group);
 }
 
-MapHandler::AnimBitmapHolder MapHandler::findObjectBitmap(const CGObjectInstance * obj, int anim, int group) const
+MapHandler::BitmapHolder MapHandler::findObjectBitmap(const CGObjectInstance * obj, int anim, int group) const
 {
 	if(!obj)
-		return MapHandler::AnimBitmapHolder();
+		return MapHandler::BitmapHolder();
 
 	// normal object
 	std::shared_ptr<Animation> animation = graphics->getAnimation(obj);
 	size_t groupSize = animation->size(group);
 	if(groupSize == 0)
-		return MapHandler::AnimBitmapHolder();
+		return MapHandler::BitmapHolder();
 	
 	animation->playerColored(obj->tempOwner);
 	auto bitmap = animation->getImage(anim % groupSize, group);
 	
 	if(!bitmap)
-		return MapHandler::AnimBitmapHolder();
+		return MapHandler::BitmapHolder();
 
 	setPlayerColor(bitmap.get(), obj->tempOwner);
 	
-	return MapHandler::AnimBitmapHolder(bitmap);
+	return MapHandler::BitmapHolder(bitmap);
 }
 
-std::vector<TileObject> & MapHandler::getObjects(int x, int y, int z)
+std::vector<ObjectRect> & MapHandler::getObjects(const int3 & tile)
 {
-	return ttiles[index(x, y, z)];
+	return tileObjects[index(tile)];
+}
+
+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, const std::set<const CGObjectInstance *> & locked)
@@ -364,36 +396,6 @@ void MapHandler::drawObjects(QPainter & painter, int x, int y, int z, const std:
 	}
 }
 
-void MapHandler::drawObject(QPainter & painter, const TileObject & object)
-{
-	const CGObjectInstance * obj = object.obj;
-	if (!obj)
-	{
-		logGlobal->error("Stray map object that isn't fading");
-		return;
-	}
-
-	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<const CGHeroInstance*>(obj), 0, obj->tempOwner, 0);
-	
-	if (objData.objBitmap)
-	{
-		auto pos = obj->getPosition();
-
-		painter.drawImage(pos.x * tileSize - object.rect.x(), pos.y * tileSize - object.rect.y(), *objData.objBitmap);
-		
-		if (objData.flagBitmap)
-		{
-			if(object.rect.x() == pos.x && object.rect.y() == pos.y)
-				painter.drawImage(pos.x * tileSize - object.rect.x(), pos.y * tileSize - object.rect.y(), *objData.flagBitmap);
-		}
-	}
-}
-
-
 void MapHandler::drawObjectAt(QPainter & painter, const CGObjectInstance * obj, int x, int y)
 {
 	if (!obj)
@@ -410,10 +412,10 @@ void MapHandler::drawObjectAt(QPainter & painter, const CGObjectInstance * obj,
 	
 	if (objData.objBitmap)
 	{
-		painter.drawImage(QPoint((x + 1) * 32 - objData.objBitmap->width(), (y + 1) * 32 - objData.objBitmap->height()), *objData.objBitmap);
+		painter.drawImage(QPoint((x + 1) * tileSize - objData.objBitmap->width(), (y + 1) * tileSize - objData.objBitmap->height()), *objData.objBitmap);
 		
 		if (objData.flagBitmap)
-			painter.drawImage(QPoint((x + 1) * 32 - objData.objBitmap->width(), (y + 1) * 32 - objData.objBitmap->height()), *objData.flagBitmap);
+			painter.drawImage(QPoint((x + 1) * tileSize - objData.objBitmap->width(), (y + 1) * tileSize - objData.objBitmap->height()), *objData.flagBitmap);
 	}
 }
 
@@ -450,107 +452,19 @@ void MapHandler::drawMinimapTile(QPainter & painter, int x, int y, int z)
 	painter.drawPoint(x, y);
 }
 
-void MapHandler::invalidate(int x, int y, int z)
+std::set<int3> MapHandler::invalidate(const CGObjectInstance * obj)
 {
-	auto & objects = getObjects(x, y, z);
-	
-	for(auto obj = objects.begin(); obj != objects.end();)
-	{
-		//object was removed
-		if(std::find(map->objects.begin(), map->objects.end(), obj->obj) == map->objects.end())
-		{
-			obj = objects.erase(obj);
-			continue;
-		}
-			
-		//object was moved
-		auto & pos = obj->obj->pos;
-		if(pos.z != z || pos.x < x || pos.y < y || pos.x - obj->obj->getWidth() >= x || pos.y - obj->obj->getHeight() >= y)
-		{
-			obj = objects.erase(obj);
-			continue;
-		}
-		
-		++obj;
-	}
+	auto t1 = removeObject(obj);
+	auto t2 = addObject(obj);
+	t1.insert(t2.begin(), t2.end());
 	
-	stable_sort(objects.begin(), objects.end(), objectBlitOrderSorter);
-}
-
-void MapHandler::invalidate(CGObjectInstance * obj)
-{
-	std::shared_ptr<Animation> animation = graphics->getAnimation(obj);
-		
-	//no animation at all or empty animation
-	if(!animation || animation->size(0) == 0)
-		return;
-		
-	auto image = animation->getImage(0, obj->ID == Obj::HERO ? 2 : 0);
-	if(!image)
-		return;
+	for(auto & tt : t2)
+		stable_sort(tileObjects[index(tt)].begin(), tileObjects[index(tt)].end(), objectBlitOrderSorter);
 	
-	for(int fx=0; fx < obj->getWidth(); ++fx)
-	{
-		for(int fy=0; fy < obj->getHeight(); ++fy)
-		{
-			//object presented on the tile
-			int3 currTile(obj->pos.x - fx, obj->pos.y - fy, obj->pos.z);
-			QRect cr(image->width() - fx * tileSize - tileSize, image->height() - fy * tileSize - tileSize, image->width(), image->height());
-			
-			if( map->isInTheMap(currTile) && // within map
-			   cr.x() + cr.width() > 0 &&           // image has data on this tile
-			   cr.y() + cr.height() > 0)
-			{
-				auto & objects = ttiles[index(currTile)];
-				bool found = false;
-				for(auto & o : objects)
-				{
-					if(o.obj == obj)
-					{
-						o.rect = cr;
-						found = true;
-						break;
-					}
-				}
-				if(!found)
-					objects.emplace_back(obj, cr);
-				
-				stable_sort(objects.begin(), objects.end(), objectBlitOrderSorter);
-			}
-		}
-	}
-}
-
-std::vector<int3> MapHandler::getTilesUnderObject(CGObjectInstance * obj) const
-{
-	std::vector<int3> result;
-	for(int fx=0; fx < obj->getWidth(); ++fx)
-	{
-		for(int fy=0; fy < obj->getHeight(); ++fy)
-		{
-			//object presented on the tile
-			int3 currTile(obj->pos.x - fx, obj->pos.y - fy, obj->pos.z);
-			if(map->isInTheMap(currTile)) // within map
-			{
-				result.push_back(currTile);
-			}
-		}
-	}
-	return result;
+	return t1;
 }
 
 void MapHandler::invalidateObjects()
 {
-	for(auto obj : map->objects)
-	{
-		invalidate(obj);
-	}
-}
-
-void MapHandler::invalidate(const std::vector<int3> & tiles)
-{
-	for(auto & currTile : tiles)
-	{
-		invalidate(currTile.x, currTile.y, currTile.z);
-	}
+	initObjectRects();
 }

+ 24 - 26
mapeditor/maphandler.h

@@ -29,26 +29,26 @@ class PlayerColor;
 
 VCMI_LIB_NAMESPACE_END
 
-struct TileObject
+struct ObjectRect
 {
-	CGObjectInstance *obj;
+	const CGObjectInstance * obj;
 	QRect rect;
 	
-	TileObject(CGObjectInstance *obj_, QRect rect_);
-	~TileObject();
+	ObjectRect(const CGObjectInstance * obj_, QRect rect_);
+	~ObjectRect();
 };
 
-using TileObjects = std::vector<TileObject>; //pointers to objects being on this tile with rects to be easier to blit this tile on screen
+using TileObjects = std::vector<ObjectRect>; //pointers to objects being on this tile with rects to be easier to blit this tile on screen
 
 class MapHandler
 {
 public:
-	struct AnimBitmapHolder
+	struct BitmapHolder
 	{
 		std::shared_ptr<QImage> objBitmap; // main object bitmap
 		std::shared_ptr<QImage> flagBitmap; // flag bitmap for the object (probably only for heroes and boats with heroes)
 		
-		AnimBitmapHolder(std::shared_ptr<QImage> objBitmap_ = nullptr, std::shared_ptr<QImage> flagBitmap_ = nullptr)
+		BitmapHolder(std::shared_ptr<QImage> objBitmap_ = nullptr, std::shared_ptr<QImage> flagBitmap_ = nullptr)
 		: objBitmap(objBitmap_),
 		flagBitmap(flagBitmap_)
 		{}
@@ -61,7 +61,7 @@ private:
 		
 	std::shared_ptr<QImage> findFlagBitmapInternal(std::shared_ptr<Animation> animation, int anim, int group, ui8 dir, bool moving) const;
 	std::shared_ptr<QImage> findFlagBitmap(const CGHeroInstance * obj, int anim, const PlayerColor color, int group) const;
-	AnimBitmapHolder findObjectBitmap(const CGObjectInstance * obj, int anim, int group = 0) const;
+	BitmapHolder findObjectBitmap(const CGObjectInstance * obj, int anim, int group = 0) const;
 	
 	//FIXME: unique_ptr should be enough, but fails to compile in MSVS 2013
 	typedef std::map<std::string, std::shared_ptr<Animation>> TFlippedAnimations; //[type, rotation]
@@ -76,28 +76,22 @@ private:
 	TFlippedAnimations riverAnimations;//[river type, rotation]
 	TFlippedCache riverImages;//[river type, view type, rotation]
 	
-	std::vector<TileObjects> ttiles; //informations about map tiles
-	int3 sizes; //map size (x = width, y = height, z = number of levels)
-	const CMap * map;
-		
-	enum class EMapCacheType : char
-	{
-		TERRAIN, OBJECTS, ROADS, RIVERS, FOW, HEROES, HERO_FLAGS, FRAME, AFTER_LAST
-	};
+	std::vector<TileObjects> tileObjects; //informations about map tiles
+	std::map<const CGObjectInstance *, std::set<int3>> tilesCache; //set of tiles beloging to object
+	
+	const CMap * map = nullptr;
 	
 	void initObjectRects();
 	void initTerrainGraphics();
 	QRgb getTileColor(int x, int y, int z);
-
-	QPolygon lockBitMask;
+	
+	std::shared_ptr<QImage> getObjectImage(const CGObjectInstance * obj);
 		
 public:
 	MapHandler();
 	~MapHandler() = default;
 	
 	void reset(const CMap * Map);
-
-	void updateWater();
 	
 	void drawTerrainTile(QPainter & painter, int x, int y, int z);
 	/// draws a river segment on current tile
@@ -105,17 +99,21 @@ public:
 	/// draws a road segment on current tile
 	void drawRoad(QPainter & painter, int x, int y, int z);
 	
-	void invalidate(int x, int y, int z); //invalidates all objects in particular tile
-	void invalidate(CGObjectInstance *); //invalidates object rects
-	void invalidate(const std::vector<int3> &); //invalidates all tiles
+	std::set<int3> invalidate(const CGObjectInstance *); //invalidates object rects
 	void invalidateObjects(); //invalidates all objects on the map
-	std::vector<int3> getTilesUnderObject(CGObjectInstance *) const;
+	const std::set<int3> & getTilesUnderObject(const CGObjectInstance *) const;
+	
+	//get objects at position
+	std::vector<ObjectRect> & getObjects(const int3 & tile);
+	std::vector<ObjectRect> & getObjects(int x, int y, int z);
+	
+	//returns set of tiles to draw
+	std::set<int3> removeObject(const CGObjectInstance * object);
+	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, const std::set<const CGObjectInstance *> & locked);
-	void drawObject(QPainter & painter, const TileObject & object);
 	void drawObjectAt(QPainter & painter, const CGObjectInstance * object, int x, int y);
-	std::vector<TileObject> & getObjects(int x, int y, int z);
 	
 	void drawMinimapTile(QPainter & painter, int x, int y, int z);
 

+ 4 - 4
mapeditor/scenelayer.cpp

@@ -518,7 +518,7 @@ CGObjectInstance * SelectionObjectsLayer::selectObjectAt(int x, int y, const CGO
 		
 		if(object.obj->visitableAt(x, y))
 		{
-			return object.obj;
+			return const_cast<CGObjectInstance*>(object.obj);
 		}
 	}
 	
@@ -530,7 +530,7 @@ CGObjectInstance * SelectionObjectsLayer::selectObjectAt(int x, int y, const CGO
 		
 		if(object.obj->blockingAt(x, y))
 		{
-			return object.obj;
+			return const_cast<CGObjectInstance*>(object.obj);
 		}
 	}
 	
@@ -542,7 +542,7 @@ CGObjectInstance * SelectionObjectsLayer::selectObjectAt(int x, int y, const CGO
 		
 		if(object.obj->coveringAt(x, y))
 		{
-			return object.obj;
+			return const_cast<CGObjectInstance*>(object.obj);
 		}
 	}
 	
@@ -568,7 +568,7 @@ void SelectionObjectsLayer::selectObjects(int x1, int y1, int x2, int y2)
 			{
 				for(auto & o : handler->getObjects(i, j, scene->level))
 					if(!lockedObjects.count(o.obj))
-						selectObject(o.obj, false); //do not inform about each object added
+						selectObject(const_cast<CGObjectInstance*>(o.obj), false); //do not inform about each object added
 			}
 		}
 	}