From 0f7d17589649b197759d0a3a801063377cb872d9 Mon Sep 17 00:00:00 2001 From: beegee1 Date: Fri, 26 Apr 2013 15:57:47 +0000 Subject: [PATCH] - Fixed all unit test failures and a few more bugs - Simplified view generation algorithm --- config/terrainViewPatterns.json | 646 ++++++++++---------------------- lib/mapping/CMapEditManager.cpp | 158 ++++---- lib/mapping/CMapEditManager.h | 21 +- test/CMapEditManagerTest.cpp | 2 +- test/TerrainViewTest.h3m | Bin 4223 -> 4214 bytes test/terrainViewMappings.json | 22 +- 6 files changed, 297 insertions(+), 552 deletions(-) diff --git a/config/terrainViewPatterns.json b/config/terrainViewPatterns.json index 6cef00f8b..8d6a389ab 100644 --- a/config/terrainViewPatterns.json +++ b/config/terrainViewPatterns.json @@ -1,467 +1,213 @@ // Defines terrain view patterns. -// The following properties are mandatory: -// data: the 3x3 pattern -// mapping: maps the pattern to a range of terrain view images/frames of the .DEF, e.g. 10-15 -// for patterns which represent two transitions a comma can be used to distinct between dirt and sand -// e.g. 10-15, 25-35 whereas the first value is always dirt and the second sand - -// The following properties are optional: -// flipMode: should the same be flipped or different images be used(see rock) or is flip not supported at all; allowed values: sameImage | diffImages; default is: sameImage -// id: the identifier for the pattern if it's referenced by other patterns -// minPoints: the minimum points to reach to validate the pattern successfully - // The following table shows the rules for the 3x3 pattern of all terrain types: // I) normal(e.g. grass, lava, ...): // N: Native type // D: Dirt border // S: Sand border // T: Sand OR dirt border(all Ts in the pattern are replaced by dirt OR sand) -// ?: T or N +// ?: D,S or N // II) dirt: // N: Native type -// D: Dirt border // S: Sand border // ?: Any border // III) sand: -// N: Native type -// S: Sand border -// IV) water: -// N: Native type -// S: Sand border -// ?: Any border -// V) rock: +// No rules +// IV) water, rock: // N: Native type // S: Sand border // ?: Any border -// Some additional info: -// Rules can be combined with comma. e.g. T, N which would be the same meaning of ?. It's most useful in combination with pattern chaining. -// Chaining of patterns is supported. To reference a another pattern you simply add the to the relevant field of the pattern. -// Rules can be given points: <[Rule OR Ref Id]-Points> With the property minPoints simple conditions can be built. - -{ - "normal" : - [ - // Standard transitions - { - "id" : "s1", - "data" : - [ - "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" : - [ - "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" : - [ - "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" - }, - { - "id" : "s4", - "data" : - [ - "N", "N", "N", - "N", "N", "s3-1", - "N", "s2-1", "T" - ], - "mapping" : "12-15, 32-35", - "minPoints" : 2 - }, - { - "id" : "s5", - "data" : - [ - "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 - }, - { - "id" : "s6", - "data" : - [ - "N", "N", "N", - "N", "N", "s5-1,N", - "N", "s5-1,N", "T" - ], - "mapping" : "18-19, 38-39", - "minPoints" : 1 - }, - // Mixed transitions - { - "id" : "m1", - "data" : - [ - "T", "N", "N", - "N", "N", "N", - "N", "N", "T" - ], - "mapping" : "40, 42" - }, - { - "id" : "m2", - "data" : - [ - "D", "N", "N", - "N", "N", "N", - "N", "N", "S" - ], - "mapping" : "41" - }, - { - "id" : "m3", - "data" : - [ - "N", "N", "D,N", - "N", "N", "D", - "S", "D,N", "D,N" - ], - "mapping" : "43" - }, - { - "id" : "m4", - "data" : - [ - "N", "N", "S", - "N", "N", "D", - "D,N", "D", "D,N" - ], - "mapping" : "44" - }, - { - "id" : "m5", - "data" : - [ - "N", "N", "D", - "N", "N", "D", - "N", "N", "S" - ], - "mapping" : "45" - }, - { - "id" : "m6", - "data" : - [ - "N", "N", "N", - "N", "N", "N", - "D,N", "D", "S" - ], - "mapping" : "46" - }, - { - "id" : "m7", - "data" : - [ - "N", "N", "?", - "N", "N", "S", - "D-1,N", "D-1,N", "?" - ], - "minPoints" : 1, - "mapping" : "47" - }, - { - "id" : "m8", - "data" : - [ - "N", "N", "D", - "N", "N", "D", - "?", "S", "?" - ], - "mapping" : "48" - }, - // No transition - { - "id" : "n1", - "data" : - [ - "N", "N", "N", - "N", "N", "N", - "N", "N", "N" - ], - "mapping" : "49-72" - } - ], - "dirt" : - [ - // Standard transitions - { - "id" : "s1", - "data" : - [ - "?", "S", "S", - "S", "N", "N", - "S", "N", "N" - ], - "mapping" : "0-3" - }, - { - "id" : "s2", - "data" : - [ - "?", "D", "D", - "S", "N", "N", - "?", "D", "D" - ], - "mapping" : "4-7" - }, - { - "id" : "s3", - "data" : - [ - "?", "S", "?", - "D", "N", "D", - "D", "N", "D" - ], - "mapping" : "8-11" - }, - { - "id" : "s4", - "data" : - [ - "D", "D", "D", - "D", "N", "?", - "D", "?", "S" - ], - "mapping" : "12-15" - }, - { - "id" : "s5", - "data" : - [ - "S", "S", "D", - "S", "N", "s6-1,D", - "D", "s6-1,D", "D" - ], - "mapping" : "16-17", - "minPoints" : 1 - }, - { - "id" : "s6", - "data" : - [ - "D", "D", "D", - "D", "N", "s5-1,D", - "D", "s5-1,D", "S" - ], - "mapping" : "18-19", - "minPoints" : 1 - }, - // Mixed transition - { - "id" : "m1", - "data" : - [ - "S", "D", "D", - "D", "N", "D", - "D", "D", "S" - ], - "mapping" : "20" - }, - // No transition - { - "id" : "n1", - "data" : - [ - "D", "D", "D", - "D", "N", "D", - "D", "D", "D" - ], - "mapping" : "21-44" - } - ], - "sand" : - [ - { - "id" : "n1", - "data" : - [ - "?", "?", "?", - "?", "N", "?", - "?", "?", "?" - ], - "mapping" : "0-23" - } - ], - "water" : - [ - // Standard transitions - { - "id" : "s1", - "data" : - [ - "S", "S", "S", - "S", "N", "N", - "S", "N", "N" - ], - "mapping" : "0-3" - }, - { - "id" : "s2", - "data" : - [ - "?", "N", "N", - "S", "N", "N", - "?", "N", "N" - ], - "mapping" : "4-7" - }, - { - "id" : "s3", - "data" : - [ - "?", "S", "?", - "N", "N", "N", - "N", "N", "N" - ], - "mapping" : "8-11" - }, - { - "id" : "s4", - "data" : - [ - "N", "N", "N", - "N", "N", "N", - "N", "N", "S" - ], - "mapping" : "12-15" - }, - { - "id" : "s5", - "data" : - [ - "S", "S", "N,S-1", - "S", "N", "N", - "N,S-1", "N", "N" - ], - "mapping" : "16-17", - "maxPoints" : 1 - }, - { - "id" : "s6", - "data" : - [ - "N", "N", "N", - "N", "N", "s5-1,N", - "N", "s5-1,N", "S" - ], - "mapping" : "18-19", - "minPoints" : 1 - }, - // No transition - { - "id" : "n1", - "data" : - [ - "N", "N", "N", - "N", "N", "N", - "N", "N", "N" - ], - "mapping" : "20-32" - } - ], - "rock" : - [ - // No transition - { - "id" : "n1", - "data" : - [ - "N", "N", "N", - "N", "N", "N", - "N", "N", "N" - ], - "mapping" : "0-7" - }, - // Standard transitions - { - "id" : "s1", - "data" : - [ - "?", "S", "?", - "S", "N", "N", - "?", "N", "N" - ], - "mapping" : "8-15", - "flipMode" : "diffImages" - }, - { - "id" : "s2", - "data" : - [ - "?", "N", "N", - "S", "N", "N", - "?", "N", "N" - ], - "mapping" : "16-19", - "flipMode" : "diffImages" - }, - { - "id" : "s3", - "data" : - [ - "?", "S", "?", - "N", "N", "N", - "N", "N", "N" - ], - "mapping" : "20-23", - "flipMode" : "diffImages" - }, - { - "id" : "s4", - "data" : - [ - "N", "N", "N", - "N", "N", "N", - "N", "N", "S" - ], - "mapping" : "24-31", - "flipMode" : "diffImages" - }, - { - "id" : "s5", - "data" : - [ - "S", "S", "N", - "S", "N", "N", - "N", "N", "N" - ], - "mapping" : "32-39", - "flipMode" : "diffImages" - }, - { - "id" : "s6", - "data" : - [ - "N", "N", "N", - "N", "N", "s5-1,N", - "N", "s5-1,N", "S" - ], - "mapping" : "40-47", - "flipMode" : "diffImages", - "minPoints" : 1 - } - ] -} +// The order of the patterns is important, do not change! +[ + // Extended mixed transitions + { + "id" : "x1", + "data" : + [ + "T", "N", "N", + "N", "N", "T", + "N", "T", "T" + ], + "mapping" : { "normal" : "73,74", "dirt" : "45" } + }, + { + "id" : "x2", + "data" : + [ + "D", "D", "N", + "D", "N", "N", + "N", "N", "S" + ], + "mapping" : { "normal" : "75" } + }, + { + "id" : "x3", + "data" : + [ + "S", "S", "N", + "S", "N", "N", + "N", "N", "D" + ], + "mapping" : { "normal" : "76" } + }, + // No transition + { + "id" : "n1", + "data" : + [ + "N", "N", "N", + "N", "N", "N", + "N", "N", "N" + ], + "mapping" : { "normal" : "49-72", "dirt" : "21-44", "sand" : "0-23", "water" : "20-32", "rock": "0-7" } + }, + // Mixed transitions + { + "id" : "m1", + "data" : + [ + "T", "N", "N", + "N", "N", "N", + "N", "N", "T" + ], + "mapping" : { "normal" : "40, 42", "dirt" : "20" } + }, + { + "id" : "m2", + "data" : + [ + "D", "N", "N", + "N", "N", "N", + "N", "N", "S" + ], + "mapping" : { "normal" : "41" } + }, + { + "id" : "m3", + "data" : + [ + "N", "N", "D,N", + "N", "N", "D", + "S", "D,N", "D,N" + ], + "mapping" : { "normal" : "43" } + }, + { + "id" : "m4", + "data" : + [ + "N", "N", "S", + "N", "N", "D", + "D,N", "D", "D,N" + ], + "mapping" : { "normal" : "44" } + }, + { + "id" : "m5", + "data" : + [ + "N", "N", "D", + "N", "N", "D", + "N", "N", "S" + ], + "mapping" : { "normal" : "45" } + }, + { + "id" : "m6", + "data" : + [ + "N", "N", "N", + "N", "N", "N", + "D,N", "D", "S" + ], + "mapping" : { "normal" : "46" } + }, + { + "id" : "m7", + "data" : + [ + "N", "N", "?", + "N", "N", "S", + "D-1,N", "D-1,N", "?" + ], + "minPoints" : 1, + "mapping" : { "normal" : "47" } + }, + { + "id" : "m8", + "data" : + [ + "N", "N", "D-1,N", + "N", "N", "D-1,N", + "?", "S", "?" + ], + "minPoints" : 1, + "mapping" : { "normal" : "48" } + }, + // Standard transitions + { + "id" : "s1", + "data" : + [ + "T,N-1", "T,N-2", "T,N-3", + "T,N-2", "N", "N", + "T", "N", "N" + ], + "maxPoints" : 3, + "mapping" : { "normal" : "0-3, 20-23", "dirt" : "0-3", "water" : "0-3", "rock": "4D:8-15" } + }, + { + "id" : "s2", + "data" : + [ + "?", "N", "N", + "T", "N", "N", + "?", "N", "N" + ], + "mapping" : { "normal" : "4-7, 24-27", "dirt" : "4-7", "water" : "4-7", "rock": "2D:16-19" } + }, + { + "id" : "s3", + "data" : + [ + "?", "T", "?", + "N", "N", "N", + "N", "N", "N" + ], + "mapping" : { "normal" : "8-11, 28-31", "dirt" : "8-11", "water" : "8-11", "rock": "2D:20-23" } + }, + { + "id" : "s4", + "data" : + [ + "N", "N", "N", + "N", "N", "s3-1,m7-1,m8-1", + "N", "s2-1,m7-1,m8-1", "T" + ], + "minPoints" : 2, + "mapping" : { "normal" : "12-15, 32-35", "dirt" : "12-15", "water" : "12-15", "rock": "4D:24-31" } + }, + { + "id" : "s5", + "data" : + [ + "T", "T", "?", + "T", "N", "s6-1,m1-1,m2-1,N", + "?", "s6-1,m1-1,m2-1,N", "N" + ], + "minPoints" : 1, + "mapping" : { "normal" : "16-17, 36-37", "dirt" : "16-17", "water" : "16-17", "rock": "4D:32-39" } + }, + { + "id" : "s6", + "data" : + [ + "N", "N", "N", + "N", "N", "s5-1,N", + "N", "s5-1,N", "T" + ], + "minPoints" : 1, + "mapping" : { "normal" : "18-19, 38-39", "dirt" : "18-19", "water" : "18-19", "rock": "4D:40-47" } + } +] diff --git a/lib/mapping/CMapEditManager.cpp b/lib/mapping/CMapEditManager.cpp index edc9daa01..a4ccdd5db 100644 --- a/lib/mapping/CMapEditManager.cpp +++ b/lib/mapping/CMapEditManager.cpp @@ -213,8 +213,7 @@ CMapUndoManager & CMapEditManager::getUndoManager() return undoManager; } -const std::string TerrainViewPattern::FLIP_MODE_SAME_IMAGE = "sameImage"; -const std::string TerrainViewPattern::FLIP_MODE_DIFF_IMAGES = "diffImages"; +const std::string TerrainViewPattern::FLIP_MODE_DIFF_IMAGES = "D"; const std::string TerrainViewPattern::RULE_DIRT = "D"; const std::string TerrainViewPattern::RULE_SAND = "S"; @@ -222,10 +221,9 @@ const std::string TerrainViewPattern::RULE_TRANSITION = "T"; const std::string TerrainViewPattern::RULE_NATIVE = "N"; const std::string TerrainViewPattern::RULE_ANY = "?"; -TerrainViewPattern::TerrainViewPattern() : minPoints(0), flipMode(FLIP_MODE_SAME_IMAGE), - terGroup(ETerrainGroup::NORMAL) +TerrainViewPattern::TerrainViewPattern() : diffImages(false), rotationTypesCount(0), minPoints(0), terGroup(ETerrainGroup::NORMAL) { - + maxPoints = std::numeric_limits::max(); } TerrainViewPattern::WeightedRule::WeightedRule() : points(0) @@ -252,67 +250,70 @@ CTerrainViewPatternConfig & CTerrainViewPatternConfig::get() CTerrainViewPatternConfig::CTerrainViewPatternConfig() { const JsonNode config(ResourceID("config/terrainViewPatterns.json")); - const auto & groupMap = config.Struct(); - BOOST_FOREACH(const auto & groupPair, groupMap) + const auto & patternsVec = config.Vector(); + BOOST_FOREACH(const auto & ptrnNode, patternsVec) { - auto terGroup = getTerrainGroup(groupPair.first); - BOOST_FOREACH(const JsonNode & ptrnNode, groupPair.second.Vector()) + TerrainViewPattern pattern; + + // Read pattern data + const JsonVector & data = ptrnNode["data"].Vector(); + assert(data.size() == 9); + for(int i = 0; i < data.size(); ++i) { - TerrainViewPattern pattern; - - // Read pattern data - const JsonVector & data = ptrnNode["data"].Vector(); - if(data.size() != 9) + std::string cell = data[i].String(); + boost::algorithm::erase_all(cell, " "); + std::vector rules; + boost::split(rules, cell, boost::is_any_of(",")); + BOOST_FOREACH(std::string ruleStr, rules) { - throw std::runtime_error("Size of pattern's data vector has to be 9."); - } - for(int i = 0; i < data.size(); ++i) - { - std::string cell = data[i].String(); - boost::algorithm::erase_all(cell, " "); - std::vector rules; - boost::split(rules, cell, boost::is_any_of(",")); - BOOST_FOREACH(std::string ruleStr, rules) + std::vector ruleParts; + boost::split(ruleParts, ruleStr, boost::is_any_of("-")); + TerrainViewPattern::WeightedRule rule; + rule.name = ruleParts[0]; + assert(!rule.name.empty()); + if(ruleParts.size() > 1) { - std::vector ruleParts; - boost::split(ruleParts, ruleStr, boost::is_any_of("-")); - TerrainViewPattern::WeightedRule rule; - rule.name = ruleParts[0]; - if(ruleParts.size() > 1) - { - rule.points = boost::lexical_cast(ruleParts[1]); - } - pattern.data[i].push_back(rule); + rule.points = boost::lexical_cast(ruleParts[1]); } + pattern.data[i].push_back(rule); } + } - // Read mapping - std::string mappingStr = ptrnNode["mapping"].String(); + // Read various properties + pattern.id = ptrnNode["id"].String(); + assert(!pattern.id.empty()); + pattern.minPoints = static_cast(ptrnNode["minPoints"].Float()); + pattern.maxPoints = static_cast(ptrnNode["maxPoints"].Float()); + if(pattern.maxPoints == 0) pattern.maxPoints = std::numeric_limits::max(); + + // Read mapping + const auto & mappingStruct = ptrnNode["mapping"].Struct(); + BOOST_FOREACH(const auto & mappingPair, mappingStruct) + { + TerrainViewPattern terGroupPattern = pattern; + auto mappingStr = mappingPair.second.String(); boost::algorithm::erase_all(mappingStr, " "); + auto colonIndex = mappingStr.find_first_of(":"); + const auto & flipMode = mappingStr.substr(0, colonIndex); + terGroupPattern.diffImages = TerrainViewPattern::FLIP_MODE_DIFF_IMAGES == &(flipMode[flipMode.length() - 1]); + if(terGroupPattern.diffImages) + { + terGroupPattern.rotationTypesCount = boost::lexical_cast(flipMode.substr(0, flipMode.length() - 1)); + assert(terGroupPattern.rotationTypesCount == 2 || terGroupPattern.rotationTypesCount == 4); + } + mappingStr = mappingStr.substr(colonIndex + 1); std::vector mappings; boost::split(mappings, mappingStr, boost::is_any_of(",")); BOOST_FOREACH(std::string mapping, mappings) { std::vector range; boost::split(range, mapping, boost::is_any_of("-")); - pattern.mapping.push_back(std::make_pair(boost::lexical_cast(range[0]), + terGroupPattern.mapping.push_back(std::make_pair(boost::lexical_cast(range[0]), boost::lexical_cast(range.size() > 1 ? range[1] : range[0]))); } - - // Read optional attributes - pattern.id = ptrnNode["id"].String(); - assert(!pattern.id.empty()); - pattern.minPoints = static_cast(ptrnNode["minPoints"].Float()); - pattern.maxPoints = static_cast(ptrnNode["maxPoints"].Float()); - if(pattern.maxPoints == 0) pattern.maxPoints = std::numeric_limits::max(); - pattern.flipMode = ptrnNode["flipMode"].String(); - if(pattern.flipMode.empty()) - { - pattern.flipMode = TerrainViewPattern::FLIP_MODE_SAME_IMAGE; - } - - pattern.terGroup = terGroup; - patterns[terGroup].push_back(pattern); + const auto & terGroup = getTerrainGroup(mappingPair.first); + terGroupPattern.terGroup = terGroup; + patterns[terGroup].push_back(terGroupPattern); } } } @@ -332,23 +333,22 @@ ETerrainGroup::ETerrainGroup CTerrainViewPatternConfig::getTerrainGroup(const st return it->second; } - const std::vector & CTerrainViewPatternConfig::getPatternsForGroup(ETerrainGroup::ETerrainGroup terGroup) const { return patterns.find(terGroup)->second; } -const TerrainViewPattern & CTerrainViewPatternConfig::getPatternById(ETerrainGroup::ETerrainGroup terGroup, const std::string & id) const +boost::optional CTerrainViewPatternConfig::getPatternById(ETerrainGroup::ETerrainGroup terGroup, const std::string & id) const { const std::vector & groupPatterns = getPatternsForGroup(terGroup); BOOST_FOREACH(const TerrainViewPattern & pattern, groupPatterns) { if(id == pattern.id) { - return pattern; + return boost::optional(pattern); } } - throw std::runtime_error("Pattern with ID not found: " + id); + return boost::optional(); } CDrawTerrainOperation::CDrawTerrainOperation(CMap * map, const MapRect & rect, ETerrainType terType, CRandomGenerator * gen) @@ -413,7 +413,7 @@ void CDrawTerrainOperation::updateTerrainViews(const MapRect & rect) break; } } - //assert(bestPattern != -1); + assert(bestPattern != -1); if(bestPattern == -1) { // This shouldn't be the case @@ -435,15 +435,16 @@ void CDrawTerrainOperation::updateTerrainViews(const MapRect & rect) // Set terrain view auto & tile = map->getTile(int3(x, y, rect.z)); - if(pattern.flipMode == TerrainViewPattern::FLIP_MODE_SAME_IMAGE) + if(!pattern.diffImages) { tile.terView = gen->getInteger(mapping.first, mapping.second); tile.extTileFlags = valRslt.flip; } else { - const int framesPerRot = 2; - int firstFrame = mapping.first + valRslt.flip * framesPerRot; + const int framesPerRot = (mapping.second - mapping.first + 1) / pattern.rotationTypesCount; + int flip = (pattern.rotationTypesCount == 2 && valRslt.flip == 2) ? 1 : valRslt.flip; + int firstFrame = mapping.first + flip * framesPerRot; tile.terView = gen->getInteger(firstFrame, firstFrame + framesPerRot - 1); tile.extTileFlags = 0; } @@ -522,12 +523,12 @@ CDrawTerrainOperation::ValidationResult CDrawTerrainOperation::validateTerrainVi TerrainViewPattern::WeightedRule rule = pattern.data[i][j]; if(!rule.isStandardRule()) { - if(recDepth == 0) + if(recDepth == 0 && map->isInTheMap(currentPos)) { - if(map->isInTheMap(currentPos) && terType == centerTerType) + const auto & patternForRule = CTerrainViewPatternConfig::get().getPatternById(getTerrainGroup(terType), rule.name); + if(patternForRule) { - const auto & patternForRule = CTerrainViewPatternConfig::get().getPatternById(pattern.terGroup, rule.name); - auto rslt = validateTerrainView(currentPos, patternForRule, 1); + auto rslt = validateTerrainView(currentPos, *patternForRule, 1); if(rslt.result) topPoints = std::max(topPoints, rule.points); } continue; @@ -538,7 +539,6 @@ CDrawTerrainOperation::ValidationResult CDrawTerrainOperation::validateTerrainVi } } - bool nativeTestOk = (rule.name == TerrainViewPattern::RULE_NATIVE || rule.name == TerrainViewPattern::RULE_ANY) && !isAlien; auto applyValidationRslt = [&](bool rslt) { if(rslt) @@ -550,11 +550,9 @@ CDrawTerrainOperation::ValidationResult CDrawTerrainOperation::validateTerrainVi // Validate cell with the ruleset of the pattern if(pattern.terGroup == ETerrainGroup::NORMAL) { - bool dirtTestOk = (rule.name == TerrainViewPattern::RULE_DIRT - || rule.name == TerrainViewPattern::RULE_TRANSITION || rule.name == TerrainViewPattern::RULE_ANY) + bool dirtTestOk = (rule.name == TerrainViewPattern::RULE_DIRT || rule.name == TerrainViewPattern::RULE_TRANSITION) && isAlien && !isSandType(terType); - bool sandTestOk = (rule.name == TerrainViewPattern::RULE_SAND || rule.name == TerrainViewPattern::RULE_TRANSITION - || rule.name == TerrainViewPattern::RULE_ANY) + bool sandTestOk = (rule.name == TerrainViewPattern::RULE_SAND || rule.name == TerrainViewPattern::RULE_TRANSITION) && isSandType(terType); if(transitionReplacement.empty() && rule.name == TerrainViewPattern::RULE_TRANSITION @@ -569,30 +567,26 @@ CDrawTerrainOperation::ValidationResult CDrawTerrainOperation::validateTerrainVi } else { - applyValidationRslt(dirtTestOk || sandTestOk || nativeTestOk); + bool nativeTestOk = rule.name == TerrainViewPattern::RULE_NATIVE && !isAlien; + applyValidationRslt(rule.name == TerrainViewPattern::RULE_ANY || dirtTestOk || sandTestOk || nativeTestOk); } } else if(pattern.terGroup == ETerrainGroup::DIRT) { - bool sandTestOk = rule.name == TerrainViewPattern::RULE_SAND && isSandType(terType); - bool dirtTestOk = rule.name == TerrainViewPattern::RULE_DIRT && !isSandType(terType) && !nativeTestOk; - applyValidationRslt(rule.name == TerrainViewPattern::RULE_ANY || sandTestOk || dirtTestOk || nativeTestOk); + bool nativeTestOk = rule.name == TerrainViewPattern::RULE_NATIVE && !isSandType(terType); + bool sandTestOk = (rule.name == TerrainViewPattern::RULE_SAND || rule.name == TerrainViewPattern::RULE_TRANSITION) + && isSandType(terType); + applyValidationRslt(rule.name == TerrainViewPattern::RULE_ANY || sandTestOk || nativeTestOk); } else if(pattern.terGroup == ETerrainGroup::SAND) { - bool sandTestOk = rule.name == TerrainViewPattern::RULE_SAND && isAlien; - applyValidationRslt(rule.name == TerrainViewPattern::RULE_ANY || sandTestOk || nativeTestOk); + applyValidationRslt(true); } - else if(pattern.terGroup == ETerrainGroup::WATER) + else if(pattern.terGroup == ETerrainGroup::WATER || pattern.terGroup == ETerrainGroup::ROCK) { - bool sandTestOk = rule.name == TerrainViewPattern::RULE_SAND && terType != ETerrainType::DIRT - && terType != ETerrainType::WATER; - applyValidationRslt(rule.name == TerrainViewPattern::RULE_ANY || sandTestOk || nativeTestOk); - } - else if(pattern.terGroup == ETerrainGroup::ROCK) - { - bool sandTestOk = rule.name == TerrainViewPattern::RULE_SAND && terType != ETerrainType::DIRT - && terType != ETerrainType::ROCK; + bool nativeTestOk = rule.name == TerrainViewPattern::RULE_NATIVE && !isAlien; + bool sandTestOk = (rule.name == TerrainViewPattern::RULE_SAND || rule.name == TerrainViewPattern::RULE_TRANSITION) + && isAlien; applyValidationRslt(rule.name == TerrainViewPattern::RULE_ANY || sandTestOk || nativeTestOk); } } diff --git a/lib/mapping/CMapEditManager.h b/lib/mapping/CMapEditManager.h index 952dea2c5..6e0cb152e 100644 --- a/lib/mapping/CMapEditManager.h +++ b/lib/mapping/CMapEditManager.h @@ -134,35 +134,25 @@ struct DLL_LINKAGE TerrainViewPattern struct WeightedRule { WeightedRule(); - /// Gets true if this rule is a standard rule which means that it has a value of one of the RULE_* constants. bool isStandardRule() const; /// The name of the rule. Can be any value of the RULE_* constants or a ID of a another pattern. std::string name; - /// Optional. A rule can have points. Patterns may have a minimum count of points to reach to be successful. int points; }; - /// Constant for the flip mode same image. Pattern will be flipped and the same image will be used(which is given in the mapping). - static const std::string FLIP_MODE_SAME_IMAGE; - /// Constant for the flip mode different images. Pattern will be flipped and different images will be used(mapping area is divided into 4 parts) static const std::string FLIP_MODE_DIFF_IMAGES; - /// Constant for the rule dirt, meaning a dirty border is required. static const std::string RULE_DIRT; - /// Constant for the rule sand, meaning a sandy border is required. static const std::string RULE_SAND; - /// Constant for the rule transition, meaning a dirty OR sandy border is required. static const std::string RULE_TRANSITION; - /// Constant for the rule native, meaning a native type is required. static const std::string RULE_NATIVE; - /// Constant for the rule any, meaning a native type, dirty OR sandy border is required. static const std::string RULE_ANY; @@ -189,13 +179,16 @@ struct DLL_LINKAGE TerrainViewPattern /// std::vector -> size=1: typical, size=2: if this pattern should map to two different types of borders /// std::pair -> 1st value: lower range, 2nd value: upper range std::vector > mapping; + /// If diffImages is true, different images/frames are used to place a rotated terrain view. If it's false + /// the same frame will be used and rotated. + bool diffImages; + /// The rotationTypesCount is only used if diffImages is true and holds the number how many rotation types(horizontal, etc...) + /// are supported. + int rotationTypesCount; /// 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; - ETerrainGroup::ETerrainGroup terGroup; }; @@ -206,7 +199,7 @@ public: static CTerrainViewPatternConfig & get(); const std::vector & getPatternsForGroup(ETerrainGroup::ETerrainGroup terGroup) const; - const TerrainViewPattern & getPatternById(ETerrainGroup::ETerrainGroup terGroup, const std::string & id) const; + boost::optional getPatternById(ETerrainGroup::ETerrainGroup terGroup, const std::string & id) const; ETerrainGroup::ETerrainGroup getTerrainGroup(const std::string & terGroup) const; private: diff --git a/test/CMapEditManagerTest.cpp b/test/CMapEditManagerTest.cpp index da2c85c63..56322f90c 100644 --- a/test/CMapEditManagerTest.cpp +++ b/test/CMapEditManagerTest.cpp @@ -50,7 +50,7 @@ BOOST_AUTO_TEST_CASE(CMapEditManager_DrawTerrain) // Get mapping range const auto & pattern = CTerrainViewPatternConfig::get().getPatternById(terGroup, id); - const auto & mapping = pattern.mapping; + const auto & mapping = (*pattern).mapping; const auto & positionsNode = node["pos"].Vector(); BOOST_FOREACH(const auto & posNode, positionsNode) diff --git a/test/TerrainViewTest.h3m b/test/TerrainViewTest.h3m index 78aa3e1c90bf1e98f7602c9f09003d49ebf59b12..7d74589187d5f687c5ff80550fbb6a8cfc965493 100644 GIT binary patch literal 4214 zcmV-+5Q*;}iwFP!000003&ot-jwDwRhEFclRn=q9boaRT>glqX)iWM%U>k!(FGwKU zLP7|G#FgzCgC#G>3+4g|OFRHv@;2P@I(~$vJO4jw@=J$nkZ;@<9dk0z5`RRTh&XYw zXI4t7u3!8bo&P#MK7R3q%jf_2%_ko{oPYlCv(M)rz4Pb$)%ojE=I77L*~PC?=}9#8 zkFR^p#ly!p&*z!o?Z3MRYMz~yug``*RrwA-U!5I(mto)APyG{-mqlI?`MJo8B0oZF zeDS*~H#L4!q`mlcJQ;P3$u*G~T62-T?BSNkwumG+*%#3YlN}8AyIl;J z3CLPDbqgk7J)up*wCVp8tzFF`|EFawU2|5ndXbQuFt<5Co3l5>*`@@!C7E%rSmB*O zs;cP*R1=YIvZJoUIk_aVsyREYoYuEQcEt6#k2W}ybn9zk!sHOG85kU6_#OmFVl&;y zK)<2M)*;9zB{S+>j-{#ux)VV$(H<*BJD`Y{y6aijGL-uHZk!gXrGRSSMyy43Np;p_PM?U^oAyzVYuhq0rpndWxJK^Ou(AjExob`!V7n3PxNx(h4(?`B6O9; zcbKts0Co>CT1Ii zGx4O+X{*n!K%dk%1lpRuD$oZQegKyCArND?&C8@Jc|~pJg_kmRgT5j1jL1mX=}jql zwsrv812R`RaBG)4R${N%4_ea<*IQ`qV=`iYLfEbM%R<{RQOiBm^e0P@MiZcOy3#j3b3d6 zDETe0yNfOd**I>XZM-9PJAcM$JIBthtAVeph5ZSky&_`wriJYM!vV_bf^-j00{fCI zFLwgh(4u(KmX#_#BRMf)ZgVKou{3l@w)xA#J_fN9C?X04a)3vXoZM2&PKQ$)Ez@Oc z%sOKBWDMQAVXo-mvp(|zcBEwCNU6h7Bp^U@^oLm=Z zhZlQVZbR z7%d&=rkJoE(u1FsLwPEg#_?(fn9R@Cds13-*;JRd$EP`~+79$-%V0x;X8pxz71aWR zx1rNzJI(_Ut4b#~r2r8TT6x;m%2~@qa77POZ)#$%akVGbp~JnbF4y|z~Bz5-dN6#}Ls41C;il;;HE zVJ_8Iz#^u0+&7Wi_#7u;MLz$!h+WXU`z@O&LArdmZnYcRJz-zLvSva%we3v!s8v*J zyPCjBlm={PN=Kry(DWEwoS7-C31oIf;-N#b)6wdY_efQd$>~TV=TXH`eUcF^q(glZ z*jOMHU4D3#`wN7Qn zBIX79q&)!fw)c)>1;jht@z2S+R*?E@VK41HVb>8cbR^Tas-lW2(l&z9k;X^8!KvJl zS*}@Tvp5x8kqCTdo{JY({ao<2Qe~e5S2;z?+n$v#pI(Zvi-xgFx8C-$-O_5mw@N@H zi6UcY;vBcv7eSou(=4y;VLw)6E|GX1fZSJ4?l{Nr7E`m>!IBV@HtKy{gojt1-?b@A ztK6oQM`;!9qlB>wa=Q<@Ft>rP8%ysZb+}k;?U4?QqgsqfIV+CgBg{$5;(BwuLtdbb zf60mW2FY!NkA87RT6S7fu>R1Rr;ZNOueY%#n-XQ<-CU+DQ*)HBh4w?L#hpHy4?K z-Fy9qxjHt)*&R#Vv96Q*x) zcy~4t=~g(7YaJ7-!?SoHZBccpi#BCZV#W;=+wiWKXMMuO)MqeYJKoUpduLx^1QU)3%nSVP z9te{}23iHa+LlF!bQ|M5i_J~y2fdN$}eUa~BEj_&s6Vq){|VPJABzjCoi0nl3&TX5H01IdLoK7-R~tE zP9H*r)1bM5xU0x+3qs?g2#AO_pZeBxBc#rX_DKdQa`KsC=PcxtyOHBY*(`j>IjOkR zGtlZ%Nl>0`Hk>PPc&aMuy=1LaW(6eOzU;#FD0%WpqfK{X>R%{wC41BDCFE`WvgULGIlTc95OiwSX?#dGWu1+q8maeG0o+F= zTY+wS1=xLJ*h0%hiS<+^ujv-ZJ|?4XQ(l%uZN{oQ*?P}nT$K^3gByJplNo#ea$!OI zPII8&lWJ)qPlY7ZrWuVC3ry7xZ-i z(2YuIyCZkgsv4sTc{NpWWncwqI4c=;i)R;ze72WZRXJ%y>NwJ@Y4sae{n>14I&qg_ z+CJJac1_(1L+fI=uV+*?Xmu!Tc_(EdOGir$nxVV}OZGDpfM$Wg=RcM7;>5R}Nn&rw zLOuysedg`mqV(^xsB3F}=q}Q`?+VOx?10qtZ-X7s8=SUehh9leviyMdOi zz|yrk=s!n&N$@jeU8L4>aT|COL!iW zS?|2d;x=?^|Iw7^z_g3wI#!?V#n*&lB5v-u?M-y48=*jkGM$1mX4~0;N}m!ejL%js zC!lPtna(vp-{}m}JLav_ilZ;De3;aTm$>5f-EQa0n>dp&2v4w{=XB0zi)0|mPCZ(| ze~8e;J^BVfr<$gNu-;cP?8usnH&7bfyu+D*tOC0w(e}_TT%Ps51_smmi`b2i7;Sur zKm$#uWi(D>fVTZ+IR6}pIE(Boduh4ty{b#U_$47 zm)}b{YCEFylPczCQ;b{1!)Z2dnzfKD43b$^QK`T5ev|J~KW~r8L!tHF58jJZlc&h^ zOqr5pJyD-1kMwtOJUo8;cOQNF@q-ucKX~|l_rLr6y?g!D*|}DJp#fpFy&sKy>rbD2 z_{T>h&tm?z{4F|u+9csW5i(OgAYG=Z#eSkV&u-_Mt=6ir+@i|gf2$D{g{!zfA^DjK7VmB@;{H(oTL~Z zjXeF}%aapl=SC9)th5~QhfgN)M{As zdB$-my!p9n>;3yu@89FqNXpK!^!|Nq8t1-J{_*v%|FH5H9;Wr9ug_jT=eazl|M&g# MKWaFJP47zp0F%pIhX4Qo literal 4223 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 Vn?Ei+frsz<_kV8qNm=hp005glR)hcm diff --git a/test/terrainViewMappings.json b/test/terrainViewMappings.json index 532b3ac20..d5a52a041 100644 --- a/test/terrainViewMappings.json +++ b/test/terrainViewMappings.json @@ -38,7 +38,7 @@ "pattern" : "normal.m3" }, { - "pos" : [ [ 5,34,0 ] ], + "pos" : [ [ 5,34,0 ], [ 26,23,0 ] ], "pattern" : "normal.m4" }, { @@ -61,9 +61,17 @@ "pos" : [ [ 7,23,0 ] ], "pattern" : "normal.n1" }, + { + "pos" : [ [ 14,6,0 ] ], + "pattern" : "normal.x1" + }, + { + "pos" : [ [ 26,22,0 ] ], + "pattern" : "normal.x2" + }, // Dirt type { - "pos" : [ [ 22,26,0 ], [ 27,35,0 ] ], + "pos" : [ [ 22,26,0 ] ], "pattern" : "dirt.s1" }, { @@ -79,7 +87,7 @@ "pattern" : "dirt.s4" }, { - "pos" : [ [ 26,28,1 ] ], + "pos" : [ [ 26,28,1 ], [ 27,35,0 ] ], "pattern" : "dirt.s5" }, { @@ -94,6 +102,10 @@ "pos" : [ [ 20,27,1 ] ], "pattern" : "dirt.n1" }, + { + "pos" : [ [ 11,24,1 ] ], + "pattern" : "dirt.x1" + }, // Sand type { "pos" : [ [ 22,27,1 ] ], @@ -134,7 +146,7 @@ "pattern" : "rock.n1" }, { - "pos" : [ [ 11,21,1 ] ], + "pos" : [ [ 11,21,1 ], [ 10,22,1 ] ], "pattern" : "rock.s1" }, { @@ -150,7 +162,7 @@ "pattern" : "rock.s4" }, { - "pos" : [ [ 10,22,1 ] ], + "pos" : [ [ 12,24,1 ] ], "pattern" : "rock.s5" }, {