mirror of
https://github.com/vcmi/vcmi.git
synced 2024-11-28 08:48:48 +02:00
- Fixed a few bugs related to the terrain view generation - Updated CMakeLists in /test(copy resources if no source files has been changed too)
This commit is contained in:
parent
8273f323b1
commit
23f7be2a54
@ -48,30 +48,33 @@
|
||||
"id" : "s1",
|
||||
"data" :
|
||||
[
|
||||
"?", "?", "T",
|
||||
"?", "N", "N",
|
||||
"T,N-1", "T,N-2", "T,N-3",
|
||||
"T,N-2", "N", "N",
|
||||
"T", "N", "N"
|
||||
],
|
||||
"maxPoints" : 3,
|
||||
"mapping" : "0-3, 20-23"
|
||||
},
|
||||
{
|
||||
"id" : "s2",
|
||||
"data" :
|
||||
[
|
||||
"?", "N", "N",
|
||||
"T", "N", "N",
|
||||
"?", "N", "N"
|
||||
"D-1,S-2,N", "N", "N",
|
||||
"T,D-2", "N", "N",
|
||||
"D-1,S-2,N", "N", "N"
|
||||
],
|
||||
"maxPoints" : 4,
|
||||
"mapping" : "4-7, 24-27"
|
||||
},
|
||||
{
|
||||
"id" : "s3",
|
||||
"data" :
|
||||
[
|
||||
"?", "T", "?",
|
||||
"D-1,S-2,N", "T,D-2", "D-1,S-2,N",
|
||||
"N", "N", "N",
|
||||
"N", "N", "N"
|
||||
],
|
||||
"maxPoints" : 4,
|
||||
"mapping" : "8-11, 28-31"
|
||||
},
|
||||
{
|
||||
@ -79,18 +82,19 @@
|
||||
"data" :
|
||||
[
|
||||
"N", "N", "N",
|
||||
"N", "N", "N",
|
||||
"N", "N", "T"
|
||||
"N", "N", "s3-1",
|
||||
"N", "s2-1", "T"
|
||||
],
|
||||
"mapping" : "12-15, 32-35"
|
||||
"mapping" : "12-15, 32-35",
|
||||
"minPoints" : 2
|
||||
},
|
||||
{
|
||||
"id" : "s5",
|
||||
"data" :
|
||||
[
|
||||
"T", "T", "s5-1,?",
|
||||
"T", "N", "N",
|
||||
"s5-1,?", "N", "N"
|
||||
"T", "T", "?",
|
||||
"T", "N", "s6-1,m1-1,m2-1,N",
|
||||
"?", "s6-1,m1-1,m2-1,N", "N"
|
||||
],
|
||||
"mapping" : "16-17, 36-37",
|
||||
"minPoints" : 1
|
||||
@ -133,7 +137,7 @@
|
||||
[
|
||||
"N", "N", "D,N",
|
||||
"N", "N", "D",
|
||||
"S", "D", "D,N"
|
||||
"S", "D,N", "D,N"
|
||||
],
|
||||
"mapping" : "43"
|
||||
},
|
||||
@ -151,7 +155,7 @@
|
||||
"id" : "m5",
|
||||
"data" :
|
||||
[
|
||||
"N", "N", "D,N",
|
||||
"N", "N", "D",
|
||||
"N", "N", "D",
|
||||
"N", "N", "S"
|
||||
],
|
||||
@ -171,10 +175,11 @@
|
||||
"id" : "m7",
|
||||
"data" :
|
||||
[
|
||||
"N", "N", "D,S,N",
|
||||
"N", "N", "?",
|
||||
"N", "N", "S",
|
||||
"D", "D", "D,S,N"
|
||||
"D-1,N", "D-1,N", "?"
|
||||
],
|
||||
"minPoints" : 1,
|
||||
"mapping" : "47"
|
||||
},
|
||||
{
|
||||
@ -183,7 +188,7 @@
|
||||
[
|
||||
"N", "N", "D",
|
||||
"N", "N", "D",
|
||||
"D,S,N", "S", "D,S,N"
|
||||
"?", "S", "?"
|
||||
],
|
||||
"mapping" : "48"
|
||||
},
|
||||
@ -237,8 +242,8 @@
|
||||
"data" :
|
||||
[
|
||||
"D", "D", "D",
|
||||
"D", "N", "N",
|
||||
"D", "N", "S"
|
||||
"D", "N", "?",
|
||||
"D", "?", "S"
|
||||
],
|
||||
"mapping" : "12-15"
|
||||
},
|
||||
@ -347,11 +352,12 @@
|
||||
"id" : "s5",
|
||||
"data" :
|
||||
[
|
||||
"S", "S", "N",
|
||||
"S", "S", "N,S-1",
|
||||
"S", "N", "N",
|
||||
"N", "N", "N"
|
||||
"N,S-1", "N", "N"
|
||||
],
|
||||
"mapping" : "16-17",
|
||||
"maxPoints" : 1
|
||||
},
|
||||
{
|
||||
"id" : "s6",
|
||||
|
@ -301,7 +301,10 @@ CTerrainViewPatternConfig::CTerrainViewPatternConfig()
|
||||
|
||||
// Read optional attributes
|
||||
pattern.id = ptrnNode["id"].String();
|
||||
assert(!pattern.id.empty());
|
||||
pattern.minPoints = static_cast<int>(ptrnNode["minPoints"].Float());
|
||||
pattern.maxPoints = static_cast<int>(ptrnNode["maxPoints"].Float());
|
||||
if(pattern.maxPoints == 0) pattern.maxPoints = std::numeric_limits<int>::max();
|
||||
pattern.flipMode = ptrnNode["flipMode"].String();
|
||||
if(pattern.flipMode.empty())
|
||||
{
|
||||
@ -388,65 +391,59 @@ std::string CDrawTerrainOperation::getLabel() const
|
||||
|
||||
void CDrawTerrainOperation::updateTerrainViews(const MapRect & rect)
|
||||
{
|
||||
for(int i = rect.x; i < rect.x + rect.width; ++i)
|
||||
for(int x = rect.x; x < rect.x + rect.width; ++x)
|
||||
{
|
||||
for(int j = rect.y; j < rect.y + rect.height; ++j)
|
||||
for(int y = rect.y; y < rect.y + rect.height; ++y)
|
||||
{
|
||||
const auto & patterns =
|
||||
CTerrainViewPatternConfig::get().getPatternsForGroup(getTerrainGroup(map->getTile(int3(i, j, rect.z)).terType));
|
||||
CTerrainViewPatternConfig::get().getPatternsForGroup(getTerrainGroup(map->getTile(int3(x, y, rect.z)).terType));
|
||||
|
||||
// Detect a pattern which fits best
|
||||
int bestPattern = -1, bestFlip = -1;
|
||||
std::string transitionReplacement;
|
||||
int bestPattern = -1;
|
||||
ValidationResult valRslt(false);
|
||||
for(int k = 0; k < patterns.size(); ++k)
|
||||
{
|
||||
const auto & pattern = patterns[k];
|
||||
|
||||
for(int flip = 0; flip < 4; ++flip)
|
||||
valRslt = validateTerrainView(int3(x, y, rect.z), pattern);
|
||||
if(valRslt.result)
|
||||
{
|
||||
auto valRslt = validateTerrainView(int3(i, j, rect.z), flip > 0 ? getFlippedPattern(pattern, flip) : pattern);
|
||||
if(valRslt.result)
|
||||
{
|
||||
logGlobal->debugStream() << "Pattern detected at pos " << i << "x" << j << "x" << rect.z << ": P-Nr. " << k
|
||||
<< ", Flip " << flip << ", Repl. " << valRslt.transitionReplacement;
|
||||
|
||||
bestPattern = k;
|
||||
bestFlip = flip;
|
||||
transitionReplacement = valRslt.transitionReplacement;
|
||||
break;
|
||||
}
|
||||
logGlobal->debugStream() << "Pattern detected at pos " << x << "x" << y << "x" << rect.z << ": P-Nr. " << pattern.id
|
||||
<< ", Flip " << valRslt.flip << ", Repl. " << valRslt.transitionReplacement;
|
||||
bestPattern = k;
|
||||
break;
|
||||
}
|
||||
}
|
||||
//assert(bestPattern != -1);
|
||||
if(bestPattern == -1)
|
||||
{
|
||||
// This shouldn't be the case
|
||||
logGlobal->warnStream() << "No pattern detected at pos " << i << "x" << j << "x" << rect.z;
|
||||
logGlobal->warnStream() << "No pattern detected at pos " << x << "x" << y << "x" << rect.z;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get mapping
|
||||
const TerrainViewPattern & pattern = patterns[bestPattern];
|
||||
std::pair<int, int> mapping;
|
||||
if(transitionReplacement.empty())
|
||||
if(valRslt.transitionReplacement.empty())
|
||||
{
|
||||
mapping = pattern.mapping[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
mapping = transitionReplacement == TerrainViewPattern::RULE_DIRT ? pattern.mapping[0] : pattern.mapping[1];
|
||||
mapping = valRslt.transitionReplacement == TerrainViewPattern::RULE_DIRT ? pattern.mapping[0] : pattern.mapping[1];
|
||||
}
|
||||
|
||||
// Set terrain view
|
||||
auto & tile = map->getTile(int3(i, j, rect.z));
|
||||
auto & tile = map->getTile(int3(x, y, rect.z));
|
||||
if(pattern.flipMode == TerrainViewPattern::FLIP_MODE_SAME_IMAGE)
|
||||
{
|
||||
tile.terView = gen->getInteger(mapping.first, mapping.second);
|
||||
tile.extTileFlags = bestFlip;
|
||||
tile.extTileFlags = valRslt.flip;
|
||||
}
|
||||
else
|
||||
{
|
||||
const int framesPerRot = 2;
|
||||
int firstFrame = mapping.first + bestFlip * framesPerRot;
|
||||
int firstFrame = mapping.first + valRslt.flip * framesPerRot;
|
||||
tile.terView = gen->getInteger(firstFrame, firstFrame + framesPerRot - 1);
|
||||
tile.extTileFlags = 0;
|
||||
}
|
||||
@ -472,6 +469,20 @@ ETerrainGroup::ETerrainGroup CDrawTerrainOperation::getTerrainGroup(ETerrainType
|
||||
}
|
||||
|
||||
CDrawTerrainOperation::ValidationResult CDrawTerrainOperation::validateTerrainView(const int3 & pos, const TerrainViewPattern & pattern, int recDepth /*= 0*/) const
|
||||
{
|
||||
for(int flip = 0; flip < 4; ++flip)
|
||||
{
|
||||
auto valRslt = validateTerrainViewInner(pos, flip > 0 ? getFlippedPattern(pattern, flip) : pattern, recDepth);
|
||||
if(valRslt.result)
|
||||
{
|
||||
valRslt.flip = flip;
|
||||
return valRslt;
|
||||
}
|
||||
}
|
||||
return ValidationResult(false);
|
||||
}
|
||||
|
||||
CDrawTerrainOperation::ValidationResult CDrawTerrainOperation::validateTerrainViewInner(const int3 & pos, const TerrainViewPattern & pattern, int recDepth /*= 0*/) const
|
||||
{
|
||||
ETerrainType centerTerType = map->getTile(pos).terType;
|
||||
int totalPoints = 0;
|
||||
@ -488,15 +499,16 @@ CDrawTerrainOperation::ValidationResult CDrawTerrainOperation::validateTerrainVi
|
||||
// Get terrain group of the current cell
|
||||
int cx = pos.x + (i % 3) - 1;
|
||||
int cy = pos.y + (i / 3) - 1;
|
||||
int3 currentPos(cx, cy, pos.z);
|
||||
bool isAlien = false;
|
||||
ETerrainType terType;
|
||||
if(cx < 0 || cx >= map->width || cy < 0 || cy >= map->height)
|
||||
if(!map->isInTheMap(currentPos))
|
||||
{
|
||||
terType = centerTerType;
|
||||
}
|
||||
else
|
||||
{
|
||||
terType = map->getTile(int3(cx, cy, pos.z)).terType;
|
||||
terType = map->getTile(currentPos).terType;
|
||||
if(terType != centerTerType)
|
||||
{
|
||||
isAlien = true;
|
||||
@ -512,17 +524,13 @@ CDrawTerrainOperation::ValidationResult CDrawTerrainOperation::validateTerrainVi
|
||||
{
|
||||
if(recDepth == 0)
|
||||
{
|
||||
const auto & patternForRule = CTerrainViewPatternConfig::get().getPatternById(pattern.terGroup, rule.name);
|
||||
auto rslt = validateTerrainView(int3(cx, cy, pos.z), patternForRule, 1);
|
||||
if(!rslt.result)
|
||||
if(map->isInTheMap(currentPos) && terType == centerTerType)
|
||||
{
|
||||
return ValidationResult(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
topPoints = std::max(topPoints, rule.points);
|
||||
continue;
|
||||
const auto & patternForRule = CTerrainViewPatternConfig::get().getPatternById(pattern.terGroup, rule.name);
|
||||
auto rslt = validateTerrainView(currentPos, patternForRule, 1);
|
||||
if(rslt.result) topPoints = std::max(topPoints, rule.points);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -549,14 +557,20 @@ CDrawTerrainOperation::ValidationResult CDrawTerrainOperation::validateTerrainVi
|
||||
|| rule.name == TerrainViewPattern::RULE_ANY)
|
||||
&& isSandType(terType);
|
||||
|
||||
if(transitionReplacement.empty() && (rule.name == TerrainViewPattern::RULE_TRANSITION
|
||||
|| rule.name == TerrainViewPattern::RULE_ANY) && (dirtTestOk || sandTestOk))
|
||||
if(transitionReplacement.empty() && rule.name == TerrainViewPattern::RULE_TRANSITION
|
||||
&& (dirtTestOk || sandTestOk))
|
||||
{
|
||||
transitionReplacement = dirtTestOk ? TerrainViewPattern::RULE_DIRT : TerrainViewPattern::RULE_SAND;
|
||||
}
|
||||
applyValidationRslt((dirtTestOk && transitionReplacement != TerrainViewPattern::RULE_SAND)
|
||||
|| (sandTestOk && transitionReplacement != TerrainViewPattern::RULE_DIRT)
|
||||
|| nativeTestOk);
|
||||
if(rule.name == TerrainViewPattern::RULE_TRANSITION)
|
||||
{
|
||||
applyValidationRslt((dirtTestOk && transitionReplacement != TerrainViewPattern::RULE_SAND) ||
|
||||
(sandTestOk && transitionReplacement != TerrainViewPattern::RULE_DIRT));
|
||||
}
|
||||
else
|
||||
{
|
||||
applyValidationRslt(dirtTestOk || sandTestOk || nativeTestOk);
|
||||
}
|
||||
}
|
||||
else if(pattern.terGroup == ETerrainGroup::DIRT)
|
||||
{
|
||||
@ -593,12 +607,14 @@ CDrawTerrainOperation::ValidationResult CDrawTerrainOperation::validateTerrainVi
|
||||
}
|
||||
}
|
||||
|
||||
if(pattern.minPoints > totalPoints)
|
||||
if(totalPoints >= pattern.minPoints && totalPoints <= pattern.maxPoints)
|
||||
{
|
||||
return ValidationResult(true, transitionReplacement);
|
||||
}
|
||||
else
|
||||
{
|
||||
return ValidationResult(false);
|
||||
}
|
||||
|
||||
return ValidationResult(true, transitionReplacement);
|
||||
}
|
||||
|
||||
bool CDrawTerrainOperation::isSandType(ETerrainType terType) const
|
||||
|
@ -190,8 +190,8 @@ struct DLL_LINKAGE TerrainViewPattern
|
||||
/// std::pair -> 1st value: lower range, 2nd value: upper range
|
||||
std::vector<std::pair<int, int> > mapping;
|
||||
|
||||
/// The minimum points to reach to to validate the pattern successfully.
|
||||
int minPoints;
|
||||
/// The minimum and maximum points to reach to validate the pattern successfully.
|
||||
int minPoints, maxPoints;
|
||||
|
||||
/// Describes if flipping is required and which mapping should be used.
|
||||
std::string flipMode;
|
||||
@ -236,12 +236,15 @@ private:
|
||||
bool result;
|
||||
/// The replacement of a T rule, either D or S.
|
||||
std::string transitionReplacement;
|
||||
int flip;
|
||||
};
|
||||
|
||||
void updateTerrainViews(const MapRect & rect);
|
||||
ETerrainGroup::ETerrainGroup getTerrainGroup(ETerrainType terType) const;
|
||||
/// Validates the terrain view of the given position and with the given pattern.
|
||||
/// Validates the terrain view of the given position and with the given pattern. The first method wraps the
|
||||
/// second method to validate the terrain view with the given pattern in all four flip directions(horizontal, vertical).
|
||||
ValidationResult validateTerrainView(const int3 & pos, const TerrainViewPattern & pattern, int recDepth = 0) const;
|
||||
ValidationResult validateTerrainViewInner(const int3 & pos, const TerrainViewPattern & pattern, int recDepth = 0) const;
|
||||
/// Tests whether the given terrain type is a sand type. Sand types are: Water, Sand and Rock
|
||||
bool isSandType(ETerrainType terType) const;
|
||||
TerrainViewPattern getFlippedPattern(const TerrainViewPattern & pattern, int flip) const;
|
||||
|
@ -14,14 +14,15 @@ add_executable(vcmitest ${test_SRCS})
|
||||
target_link_libraries(vcmitest vcmi ${Boost_LIBRARIES})
|
||||
add_test(vcmitest vcmitest)
|
||||
|
||||
# Files to copy to the build directory after compilation
|
||||
# Files to copy to the build directory
|
||||
add_custom_target(vcmitestFiles ALL)
|
||||
set(vcmitest_FILES
|
||||
TerrainViewTest.h3m
|
||||
terrainViewMappings.json
|
||||
)
|
||||
|
||||
foreach(file ${vcmitest_FILES})
|
||||
add_custom_command(TARGET vcmitest POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_CURRENT_SOURCE_DIR}/${file}" $<TARGET_FILE_DIR:vcmitest>
|
||||
add_custom_command(TARGET vcmitestFiles POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_CURRENT_SOURCE_DIR}/${file}" ${CMAKE_CURRENT_BINARY_DIR}
|
||||
)
|
||||
endforeach()
|
||||
|
@ -26,7 +26,7 @@
|
||||
"pattern" : "normal.s6"
|
||||
},
|
||||
{
|
||||
"pos" : [ [ 21,20,1 ], [ 28,27,1 ] ],
|
||||
"pos" : [ [ 21,20,1 ], [ 28,27,0 ] ],
|
||||
"pattern" : "normal.m1"
|
||||
},
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user