Browse Source

Merge pull request #3711 from vcmi/reindex_objects

Reindex objects to show interactive objects on top
DjWarmonger 1 year ago
parent
commit
5c40aa8612
4 changed files with 42 additions and 1 deletions
  1. 37 1
      lib/mapping/CMap.cpp
  2. 2 0
      lib/mapping/CMap.h
  3. 2 0
      lib/mapping/CMapOperation.cpp
  4. 1 0
      lib/rmg/CMapGenerator.cpp

+ 37 - 1
lib/mapping/CMap.cpp

@@ -572,16 +572,18 @@ void CMap::removeObject(CGObjectInstance * obj)
 	instanceNames.erase(obj->instanceName);
 
 	//update indeces
+
 	auto iter = std::next(objects.begin(), obj->id.getNum());
 	iter = objects.erase(iter);
 	for(int i = obj->id.getNum(); iter != objects.end(); ++i, ++iter)
 	{
 		(*iter)->id = ObjectInstanceID(i);
 	}
-	
+
 	obj->afterRemoveFromMap(this);
 
 	//TOOD: Clean artifact instances (mostly worn by hero?) and quests related to this object
+	//This causes crash with undo/redo in editor
 }
 
 bool CMap::isWaterMap() const
@@ -704,4 +706,38 @@ void CMap::resolveQuestIdentifiers()
 	questIdentifierToId.clear();
 }
 
+void CMap::reindexObjects()
+{
+	// Only reindex at editor / RMG operations
+
+	std::sort(objects.begin(), objects.end(), [](const CGObjectInstance * lhs, const CGObjectInstance * rhs)
+	{
+		// Obstacles first, then visitable, at the end - removable
+
+		if (!lhs->isVisitable() && rhs->isVisitable())
+			return true;
+		if (lhs->isVisitable() && !rhs->isVisitable())
+			return false;
+
+		// Special case for Windomill - draw on top of other objects
+		if (lhs->ID != Obj::WINDMILL && rhs->ID == Obj::WINDMILL)
+			return true;
+		if (lhs->ID == Obj::WINDMILL && rhs->ID != Obj::WINDMILL)
+			return false;
+
+		if (!lhs->isRemovable() && rhs->isRemovable())
+			return true;
+		if (lhs->isRemovable() && !rhs->isRemovable())
+			return false;
+
+		return lhs->pos.y < rhs->pos.y;
+	});
+
+	// instanceNames don't change
+	for (size_t i = 0; i < objects.size(); ++i)
+	{
+		objects[i]->id = ObjectInstanceID(i);
+	}
+}
+
 VCMI_LIB_NAMESPACE_END

+ 2 - 0
lib/mapping/CMap.h

@@ -128,6 +128,8 @@ public:
 	void resetStaticData();
 	void resolveQuestIdentifiers();
 
+	void reindexObjects();
+
 	ui32 checksum;
 	std::vector<Rumor> rumors;
 	std::vector<DisposedHero> disposedHeroes;

+ 2 - 0
lib/mapping/CMapOperation.cpp

@@ -47,6 +47,8 @@ CComposedOperation::CComposedOperation(CMap* map) : CMapOperation(map)
 
 void CComposedOperation::execute()
 {
+	// FIXME: Only reindex objects at the end of composite operation
+
 	for(auto & operation : operations)
 	{
 		operation->execute();

+ 1 - 0
lib/rmg/CMapGenerator.cpp

@@ -419,6 +419,7 @@ void CMapGenerator::fillZones()
 	auto grailZone = *RandomGeneratorUtil::nextItem(treasureZones, rand);
 
 	map->getMap(this).grailPos = *RandomGeneratorUtil::nextItem(grailZone->freePaths()->getTiles(), rand);
+	map->getMap(this).reindexObjects();
 
 	logGlobal->info("Zones filled successfully");