mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
Add some debug logging, Fix one special case when updating terrain type, Improve visual look of updated terrain types
This commit is contained in:
parent
6001a89632
commit
dafaf86eef
1
.gitignore
vendored
1
.gitignore
vendored
@ -27,3 +27,4 @@ ui_*.h
|
|||||||
/CPackConfig.cmake
|
/CPackConfig.cmake
|
||||||
/CPackSourceConfig.cmake
|
/CPackSourceConfig.cmake
|
||||||
build-*
|
build-*
|
||||||
|
CMakeLists.txt.user.*
|
||||||
|
@ -88,10 +88,10 @@ CCreature * CreatureID::toCreature() const
|
|||||||
CSpell * SpellID::toSpell() const
|
CSpell * SpellID::toSpell() const
|
||||||
{
|
{
|
||||||
if(num < 0 || num >= VLC->spellh->objects.size())
|
if(num < 0 || num >= VLC->spellh->objects.size())
|
||||||
{
|
{
|
||||||
logGlobal->errorStream() << "Unable to get spell of invalid ID " << int(num);
|
logGlobal->errorStream() << "Unable to get spell of invalid ID " << int(num);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
return VLC->spellh->objects[*this];
|
return VLC->spellh->objects[*this];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,3 +129,34 @@ std::ostream & operator<<(std::ostream & os, const Battle::ActionType actionType
|
|||||||
if (it == actionTypeToString.end()) return os << "<Unknown type>";
|
if (it == actionTypeToString.end()) return os << "<Unknown type>";
|
||||||
else return os << it->second;
|
else return os << it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::ostream & operator<<(std::ostream & os, const ETerrainType actionType)
|
||||||
|
{
|
||||||
|
static const std::map<ETerrainType::EETerrainType, std::string> terrainTypeToString =
|
||||||
|
{
|
||||||
|
#define DEFINE_ELEMENT(element) {ETerrainType::element, #element}
|
||||||
|
DEFINE_ELEMENT(WRONG),
|
||||||
|
DEFINE_ELEMENT(BORDER),
|
||||||
|
DEFINE_ELEMENT(DIRT),
|
||||||
|
DEFINE_ELEMENT(SAND),
|
||||||
|
DEFINE_ELEMENT(GRASS),
|
||||||
|
DEFINE_ELEMENT(SNOW),
|
||||||
|
DEFINE_ELEMENT(SWAMP),
|
||||||
|
DEFINE_ELEMENT(ROUGH),
|
||||||
|
DEFINE_ELEMENT(SUBTERRANEAN),
|
||||||
|
DEFINE_ELEMENT(LAVA),
|
||||||
|
DEFINE_ELEMENT(WATER),
|
||||||
|
DEFINE_ELEMENT(ROCK)
|
||||||
|
};
|
||||||
|
|
||||||
|
auto it = terrainTypeToString.find(actionType.num);
|
||||||
|
if (it == terrainTypeToString.end()) return os << "<Unknown type>";
|
||||||
|
else return os << it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ETerrainType::toString() const
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << *this;
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
@ -702,7 +702,7 @@ namespace Battle
|
|||||||
|
|
||||||
std::ostream & operator<<(std::ostream & os, const Battle::ActionType actionType);
|
std::ostream & operator<<(std::ostream & os, const Battle::ActionType actionType);
|
||||||
|
|
||||||
class ETerrainType
|
class DLL_LINKAGE ETerrainType
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum EETerrainType
|
enum EETerrainType
|
||||||
@ -717,8 +717,12 @@ public:
|
|||||||
ID_LIKE_CLASS_COMMON(ETerrainType, EETerrainType)
|
ID_LIKE_CLASS_COMMON(ETerrainType, EETerrainType)
|
||||||
|
|
||||||
EETerrainType num;
|
EETerrainType num;
|
||||||
|
|
||||||
|
std::string toString() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
DLL_LINKAGE std::ostream & operator<<(std::ostream & os, const ETerrainType actionType);
|
||||||
|
|
||||||
ID_LIKE_OPERATORS_DECLS(ETerrainType, ETerrainType::EETerrainType)
|
ID_LIKE_OPERATORS_DECLS(ETerrainType, ETerrainType::EETerrainType)
|
||||||
|
|
||||||
|
|
||||||
|
@ -482,13 +482,15 @@ void CDrawTerrainOperation::updateTerrainTypes()
|
|||||||
{
|
{
|
||||||
const auto & centerPos = *(positions.begin());
|
const auto & centerPos = *(positions.begin());
|
||||||
auto centerTile = map->getTile(centerPos);
|
auto centerTile = map->getTile(centerPos);
|
||||||
|
logGlobal->debugStream() << boost::format("Set terrain tile at pos '%s' to type '%s'") % centerPos % centerTile.terType;
|
||||||
auto tiles = getInvalidTiles(centerPos);
|
auto tiles = getInvalidTiles(centerPos);
|
||||||
auto updateTerrainType = [&](const int3 & pos, bool tileRequiresValidation)
|
auto updateTerrainType = [&](const int3 & pos, bool tileRequiresValidation)
|
||||||
{
|
{
|
||||||
map->getTile(pos).terType = centerTile.terType;
|
map->getTile(pos).terType = centerTile.terType;
|
||||||
if(tileRequiresValidation) positions.insert(pos);
|
if(tileRequiresValidation) positions.insert(pos);
|
||||||
invalidateTerrainViews(pos);
|
invalidateTerrainViews(pos);
|
||||||
logGlobal->debugStream() << boost::format("Update terrain tile at '%s' to type '%i'.") % pos % centerTile.terType;
|
logGlobal->debugStream() << boost::format("Set additional terrain tile at pos '%s' to type '%s'; tileRequiresValidation '%s'") % pos
|
||||||
|
% centerTile.terType % tileRequiresValidation;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Fill foreign invalid tiles
|
// Fill foreign invalid tiles
|
||||||
@ -497,12 +499,14 @@ void CDrawTerrainOperation::updateTerrainTypes()
|
|||||||
updateTerrainType(tile, true);
|
updateTerrainType(tile, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tiles = getInvalidTiles(centerPos);
|
||||||
if(tiles.nativeTiles.find(centerPos) != tiles.nativeTiles.end())
|
if(tiles.nativeTiles.find(centerPos) != tiles.nativeTiles.end())
|
||||||
{
|
{
|
||||||
// Blow up
|
// Blow up
|
||||||
auto rect = extendTileAroundSafely(centerPos);
|
auto rect = extendTileAroundSafely(centerPos);
|
||||||
std::set<int3> suitableTiles;
|
std::set<int3> suitableTiles;
|
||||||
int invalidForeignTilesCnt = std::numeric_limits<int>::max(), invalidNativeTilesCnt = 0;
|
int invalidForeignTilesCnt = std::numeric_limits<int>::max(), invalidNativeTilesCnt = 0;
|
||||||
|
bool centerPosValid = false;
|
||||||
rect.forEach([&](const int3 & posToTest)
|
rect.forEach([&](const int3 & posToTest)
|
||||||
{
|
{
|
||||||
auto & terrainTile = map->getTile(posToTest);
|
auto & terrainTile = map->getTile(posToTest);
|
||||||
@ -511,28 +515,64 @@ void CDrawTerrainOperation::updateTerrainTypes()
|
|||||||
auto formerTerType = terrainTile.terType;
|
auto formerTerType = terrainTile.terType;
|
||||||
terrainTile.terType = centerTile.terType;
|
terrainTile.terType = centerTile.terType;
|
||||||
auto testTile = getInvalidTiles(posToTest);
|
auto testTile = getInvalidTiles(posToTest);
|
||||||
auto addToSuitableTiles = [&](const int3 & pos)
|
|
||||||
{
|
|
||||||
suitableTiles.insert(pos);
|
|
||||||
logGlobal->debugStream() << boost::format(std::string("Found suitable tile '%s' for main tile '%s': ") +
|
|
||||||
"Invalid native tiles '%i', invalid foreign tiles '%i'.") % pos % centerPos % testTile.nativeTiles.size() %
|
|
||||||
testTile.foreignTiles.size();
|
|
||||||
};
|
|
||||||
|
|
||||||
int nativeTilesCntNorm = testTile.nativeTiles.empty() ? std::numeric_limits<int>::max() : testTile.nativeTiles.size();
|
int nativeTilesCntNorm = testTile.nativeTiles.empty() ? std::numeric_limits<int>::max() : testTile.nativeTiles.size();
|
||||||
if(nativeTilesCntNorm > invalidNativeTilesCnt ||
|
|
||||||
(nativeTilesCntNorm == invalidNativeTilesCnt && testTile.foreignTiles.size() < invalidForeignTilesCnt))
|
bool putSuitableTile = false;
|
||||||
|
bool addToSuitableTiles = false;
|
||||||
|
if(testTile.centerPosValid)
|
||||||
{
|
{
|
||||||
|
if (!centerPosValid)
|
||||||
|
{
|
||||||
|
centerPosValid = true;
|
||||||
|
putSuitableTile = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(testTile.foreignTiles.size() < invalidForeignTilesCnt)
|
||||||
|
{
|
||||||
|
putSuitableTile = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
addToSuitableTiles = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!centerPosValid)
|
||||||
|
{
|
||||||
|
if((nativeTilesCntNorm > invalidNativeTilesCnt) ||
|
||||||
|
(nativeTilesCntNorm == invalidNativeTilesCnt && testTile.foreignTiles.size() < invalidForeignTilesCnt))
|
||||||
|
{
|
||||||
|
putSuitableTile = true;
|
||||||
|
}
|
||||||
|
else if(nativeTilesCntNorm == invalidNativeTilesCnt && testTile.foreignTiles.size() == invalidForeignTilesCnt)
|
||||||
|
{
|
||||||
|
addToSuitableTiles = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (putSuitableTile)
|
||||||
|
{
|
||||||
|
if(!suitableTiles.empty())
|
||||||
|
{
|
||||||
|
logGlobal->debugStream() << "Clear suitables tiles.";
|
||||||
|
}
|
||||||
|
|
||||||
invalidNativeTilesCnt = nativeTilesCntNorm;
|
invalidNativeTilesCnt = nativeTilesCntNorm;
|
||||||
invalidForeignTilesCnt = testTile.foreignTiles.size();
|
invalidForeignTilesCnt = testTile.foreignTiles.size();
|
||||||
suitableTiles.clear();
|
suitableTiles.clear();
|
||||||
addToSuitableTiles(posToTest);
|
addToSuitableTiles = true;
|
||||||
}
|
}
|
||||||
else if(nativeTilesCntNorm == invalidNativeTilesCnt &&
|
|
||||||
testTile.foreignTiles.size() == invalidForeignTilesCnt)
|
if (addToSuitableTiles)
|
||||||
{
|
{
|
||||||
addToSuitableTiles(posToTest);
|
suitableTiles.insert(posToTest);
|
||||||
|
logGlobal->debugStream() << boost::format(std::string("Found suitable tile '%s' for main tile '%s': ") +
|
||||||
|
"Invalid native tiles '%i', invalid foreign tiles '%i', centerPosValid '%i'") % posToTest % centerPos % testTile.nativeTiles.size() %
|
||||||
|
testTile.foreignTiles.size() % testTile.centerPosValid;
|
||||||
}
|
}
|
||||||
|
|
||||||
terrainTile.terType = formerTerType;
|
terrainTile.terType = formerTerType;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -591,6 +631,7 @@ void CDrawTerrainOperation::updateTerrainViews()
|
|||||||
{
|
{
|
||||||
// This shouldn't be the case
|
// This shouldn't be the case
|
||||||
logGlobal->warnStream() << boost::format("No pattern detected at pos '%s'.") % pos;
|
logGlobal->warnStream() << boost::format("No pattern detected at pos '%s'.") % pos;
|
||||||
|
CTerrainViewPatternUtils::printDebuggingInfoAboutTile(map, pos);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -878,6 +919,10 @@ CDrawTerrainOperation::InvalidTiles CDrawTerrainOperation::getInvalidTiles(const
|
|||||||
if(terType == centerTerType) tiles.nativeTiles.insert(pos);
|
if(terType == centerTerType) tiles.nativeTiles.insert(pos);
|
||||||
else tiles.foreignTiles.insert(pos);
|
else tiles.foreignTiles.insert(pos);
|
||||||
}
|
}
|
||||||
|
else if(centerPos == pos)
|
||||||
|
{
|
||||||
|
tiles.centerPosValid = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return tiles;
|
return tiles;
|
||||||
@ -899,6 +944,35 @@ CDrawTerrainOperation::ValidationResult::ValidationResult(bool result, const std
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CTerrainViewPatternUtils::printDebuggingInfoAboutTile(const CMap * map, int3 pos)
|
||||||
|
{
|
||||||
|
logGlobal->debugStream() << "Printing detailed info about nearby map tiles of pos '" << pos << "'";
|
||||||
|
for(int y = pos.y - 2; y <= pos.y + 2; ++y)
|
||||||
|
{
|
||||||
|
std::string line;
|
||||||
|
const int PADDED_LENGTH = 10;
|
||||||
|
for(int x = pos.x - 2; x <= pos.x + 2; ++x)
|
||||||
|
{
|
||||||
|
auto debugPos = int3(x, y, pos.z);
|
||||||
|
if(map->isInTheMap(debugPos))
|
||||||
|
{
|
||||||
|
auto debugTile = map->getTile(debugPos);
|
||||||
|
|
||||||
|
std::string terType = debugTile.terType.toString().substr(0, 6);
|
||||||
|
line += terType;
|
||||||
|
line.insert(line.end(), PADDED_LENGTH - terType.size(), ' ');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
line += "X";
|
||||||
|
line.insert(line.end(), PADDED_LENGTH - 1, ' ');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
logGlobal->debugStream() << line;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CClearTerrainOperation::CClearTerrainOperation(CMap * map, CRandomGenerator * gen) : CComposedOperation(map)
|
CClearTerrainOperation::CClearTerrainOperation(CMap * map, CRandomGenerator * gen) : CComposedOperation(map)
|
||||||
{
|
{
|
||||||
CTerrainSelection terrainSel(map);
|
CTerrainSelection terrainSel(map);
|
||||||
|
@ -318,6 +318,9 @@ private:
|
|||||||
struct InvalidTiles
|
struct InvalidTiles
|
||||||
{
|
{
|
||||||
std::set<int3> foreignTiles, nativeTiles;
|
std::set<int3> foreignTiles, nativeTiles;
|
||||||
|
bool centerPosValid;
|
||||||
|
|
||||||
|
InvalidTiles() : centerPosValid(false) { }
|
||||||
};
|
};
|
||||||
|
|
||||||
void updateTerrainTypes();
|
void updateTerrainTypes();
|
||||||
@ -346,6 +349,12 @@ private:
|
|||||||
std::set<int3> invalidatedTerViews;
|
std::set<int3> invalidatedTerViews;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class DLL_LINKAGE CTerrainViewPatternUtils
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static void printDebuggingInfoAboutTile(const CMap * map, int3 pos);
|
||||||
|
};
|
||||||
|
|
||||||
/// The CClearTerrainOperation clears+initializes the terrain.
|
/// The CClearTerrainOperation clears+initializes the terrain.
|
||||||
class CClearTerrainOperation : public CComposedOperation
|
class CClearTerrainOperation : public CComposedOperation
|
||||||
{
|
{
|
||||||
|
@ -71,6 +71,32 @@ BOOST_AUTO_TEST_CASE(CMapEditManager_DrawTerrain_Type)
|
|||||||
}
|
}
|
||||||
editManager->drawTerrain(ETerrainType::GRASS);
|
editManager->drawTerrain(ETerrainType::GRASS);
|
||||||
BOOST_CHECK(map->getTile(int3(35, 44, 0)).terType == ETerrainType::WATER);
|
BOOST_CHECK(map->getTile(int3(35, 44, 0)).terType == ETerrainType::WATER);
|
||||||
|
|
||||||
|
// Rock case
|
||||||
|
editManager->getTerrainSelection().selectRange(MapRect(int3(1, 1, 1), 15, 15));
|
||||||
|
editManager->drawTerrain(ETerrainType::SUBTERRANEAN);
|
||||||
|
std::vector<int3> vec({ int3(6, 6, 1), int3(7, 6, 1), int3(8, 6, 1), int3(5, 7, 1), int3(6, 7, 1), int3(7, 7, 1),
|
||||||
|
int3(8, 7, 1), int3(4, 8, 1), int3(5, 8, 1), int3(6, 8, 1)});
|
||||||
|
editManager->getTerrainSelection().setSelection(vec);
|
||||||
|
editManager->drawTerrain(ETerrainType::ROCK);
|
||||||
|
BOOST_CHECK(map->getTile(int3(5, 6, 1)).terType == ETerrainType::ROCK || map->getTile(int3(7, 8, 1)).terType == ETerrainType::ROCK);
|
||||||
|
|
||||||
|
// next check
|
||||||
|
auto map2 = make_unique<CMap>();
|
||||||
|
map2->width = 128;
|
||||||
|
map2->height = 128;
|
||||||
|
map2->initTerrain();
|
||||||
|
auto editManager2 = map2->getEditManager();
|
||||||
|
|
||||||
|
editManager2->getTerrainSelection().selectRange(MapRect(int3(0, 0, 1), 128, 128));
|
||||||
|
editManager2->drawTerrain(ETerrainType::SUBTERRANEAN);
|
||||||
|
|
||||||
|
std::vector<int3> selection({ int3(95, 43, 1), int3(95, 44, 1), int3(94, 45, 1), int3(95, 45, 1), int3(96, 45, 1),
|
||||||
|
int3(93, 46, 1), int3(94, 46, 1), int3(95, 46, 1), int3(96, 46, 1), int3(97, 46, 1),
|
||||||
|
int3(98, 46, 1), int3(99, 46, 1)});
|
||||||
|
editManager2->getTerrainSelection().setSelection(selection);
|
||||||
|
editManager2->drawTerrain(ETerrainType::ROCK);
|
||||||
|
|
||||||
}
|
}
|
||||||
catch(const std::exception & e)
|
catch(const std::exception & e)
|
||||||
{
|
{
|
||||||
@ -82,15 +108,15 @@ BOOST_AUTO_TEST_CASE(CMapEditManager_DrawTerrain_View)
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Load maps and json config
|
// Load maps and json config
|
||||||
|
|
||||||
#if defined(__MINGW32__)
|
#if defined(__MINGW32__)
|
||||||
const std::string TEST_DATA_DIR = "test/";
|
const std::string TEST_DATA_DIR = "test/";
|
||||||
#else
|
#else
|
||||||
const std::string TEST_DATA_DIR = ".";
|
const std::string TEST_DATA_DIR = ".";
|
||||||
#endif // defined
|
#endif // defined
|
||||||
|
|
||||||
|
|
||||||
auto loader = new CFilesystemLoader("test/", TEST_DATA_DIR);
|
auto loader = new CFilesystemLoader("test/", TEST_DATA_DIR);
|
||||||
dynamic_cast<CFilesystemList*>(CResourceHandler::get())->addLoader(loader, false);
|
dynamic_cast<CFilesystemList*>(CResourceHandler::get())->addLoader(loader, false);
|
||||||
const auto originalMap = CMapService::loadMap("test/TerrainViewTest");
|
const auto originalMap = CMapService::loadMap("test/TerrainViewTest");
|
||||||
@ -124,6 +150,7 @@ BOOST_AUTO_TEST_CASE(CMapEditManager_DrawTerrain_View)
|
|||||||
if(posVector.size() != 3) throw std::runtime_error("A position should consist of three values x,y,z. Continue with next position.");
|
if(posVector.size() != 3) throw std::runtime_error("A position should consist of three values x,y,z. Continue with next position.");
|
||||||
int3 pos(posVector[0].Float(), posVector[1].Float(), posVector[2].Float());
|
int3 pos(posVector[0].Float(), posVector[1].Float(), posVector[2].Float());
|
||||||
logGlobal->infoStream() << boost::format("Test pattern '%s' on position x '%d', y '%d', z '%d'.") % patternStr % pos.x % pos.y % pos.z;
|
logGlobal->infoStream() << boost::format("Test pattern '%s' on position x '%d', y '%d', z '%d'.") % patternStr % pos.x % pos.y % pos.z;
|
||||||
|
CTerrainViewPatternUtils::printDebuggingInfoAboutTile(map.get(), pos);
|
||||||
const auto & originalTile = originalMap->getTile(pos);
|
const auto & originalTile = originalMap->getTile(pos);
|
||||||
editManager->getTerrainSelection().selectRange(MapRect(pos, 1, 1));
|
editManager->getTerrainSelection().selectRange(MapRect(pos, 1, 1));
|
||||||
editManager->drawTerrain(originalTile.terType, &gen);
|
editManager->drawTerrain(originalTile.terType, &gen);
|
||||||
|
Binary file not shown.
@ -165,6 +165,10 @@
|
|||||||
"pos" : [ [ 12,24,1 ] ],
|
"pos" : [ [ 12,24,1 ] ],
|
||||||
"pattern" : "rock.s5"
|
"pattern" : "rock.s5"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"pos" : [ [ 16,4,1 ] ],
|
||||||
|
"pattern" : "rock.s5"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"pos" : [ [ 8,23,1 ] ],
|
"pos" : [ [ 8,23,1 ] ],
|
||||||
"pattern" : "rock.s6"
|
"pattern" : "rock.s6"
|
||||||
|
Loading…
Reference in New Issue
Block a user