mirror of
https://github.com/vcmi/vcmi.git
synced 2025-08-13 19:54:17 +02:00
Part 3 - first working draft, cut generation time by half.
This commit is contained in:
@@ -413,12 +413,25 @@ CTerrainViewPatternConfig::CTerrainViewPatternConfig()
|
|||||||
|
|
||||||
// Add pattern to the patterns map
|
// Add pattern to the patterns map
|
||||||
const auto & terGroup = getTerrainGroup(mappingPair.first);
|
const auto & terGroup = getTerrainGroup(mappingPair.first);
|
||||||
terrainViewPatterns[terGroup].push_back(terGroupPattern);
|
std::vector<TerrainViewPattern> terrainViewPatternFlips;
|
||||||
|
terrainViewPatternFlips.push_back(terGroupPattern);
|
||||||
|
|
||||||
|
for (int i = 1; i < 4; ++i)
|
||||||
|
{
|
||||||
|
flipPattern(pattern, i); //flip original by 90 degrees and push back copy
|
||||||
|
terrainViewPatternFlips.push_back(pattern);
|
||||||
|
}
|
||||||
|
terrainViewPatterns[terGroup].push_back(terrainViewPatternFlips);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(i == 1)
|
else if(i == 1)
|
||||||
{
|
{
|
||||||
terrainTypePatterns[pattern.id] = pattern;
|
terrainTypePatterns[pattern.id].push_back(pattern);
|
||||||
|
for (int i = 1; i < 4; ++i)
|
||||||
|
{
|
||||||
|
flipPattern(pattern, i); //flip original by 90 degrees and push back copy
|
||||||
|
terrainTypePatterns[pattern.id].push_back(pattern);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -444,16 +457,17 @@ ETerrainGroup::ETerrainGroup CTerrainViewPatternConfig::getTerrainGroup(const st
|
|||||||
return it->second;
|
return it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<TerrainViewPattern> & CTerrainViewPatternConfig::getTerrainViewPatternsForGroup(ETerrainGroup::ETerrainGroup terGroup) const
|
const std::vector<std::vector<TerrainViewPattern>> & CTerrainViewPatternConfig::getTerrainViewPatternsForGroup(ETerrainGroup::ETerrainGroup terGroup) const
|
||||||
{
|
{
|
||||||
return terrainViewPatterns.find(terGroup)->second;
|
return terrainViewPatterns.find(terGroup)->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::optional<const TerrainViewPattern &> CTerrainViewPatternConfig::getTerrainViewPatternById(ETerrainGroup::ETerrainGroup terGroup, const std::string & id) const
|
boost::optional<const TerrainViewPattern &> CTerrainViewPatternConfig::getTerrainViewPatternById(ETerrainGroup::ETerrainGroup terGroup, const std::string & id) const
|
||||||
{
|
{
|
||||||
const std::vector<TerrainViewPattern> & groupPatterns = getTerrainViewPatternsForGroup(terGroup);
|
const std::vector<std::vector<TerrainViewPattern>> & groupPatterns = getTerrainViewPatternsForGroup(terGroup);
|
||||||
for(const TerrainViewPattern & pattern : groupPatterns)
|
for (const std::vector<TerrainViewPattern> & patternFlips : groupPatterns)
|
||||||
{
|
{
|
||||||
|
const TerrainViewPattern & pattern = patternFlips.front();
|
||||||
if(id == pattern.id)
|
if(id == pattern.id)
|
||||||
{
|
{
|
||||||
return boost::optional<const TerrainViewPattern &>(pattern);
|
return boost::optional<const TerrainViewPattern &>(pattern);
|
||||||
@@ -461,14 +475,54 @@ boost::optional<const TerrainViewPattern &> CTerrainViewPatternConfig::getTerrai
|
|||||||
}
|
}
|
||||||
return boost::optional<const TerrainViewPattern &>();
|
return boost::optional<const TerrainViewPattern &>();
|
||||||
}
|
}
|
||||||
|
boost::optional<const std::vector<TerrainViewPattern> &> CTerrainViewPatternConfig::getTerrainViewPatternsById(ETerrainGroup::ETerrainGroup terGroup, const std::string & id) const
|
||||||
|
{
|
||||||
|
const std::vector<std::vector<TerrainViewPattern>> & groupPatterns = getTerrainViewPatternsForGroup(terGroup);
|
||||||
|
for (const std::vector<TerrainViewPattern> & patternFlips : groupPatterns)
|
||||||
|
{
|
||||||
|
const TerrainViewPattern & pattern = patternFlips.front();
|
||||||
|
if (id == pattern.id)
|
||||||
|
{
|
||||||
|
return boost::optional<const std::vector<TerrainViewPattern> &>(patternFlips);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return boost::optional<const std::vector<TerrainViewPattern> &>();
|
||||||
|
}
|
||||||
|
|
||||||
const TerrainViewPattern & CTerrainViewPatternConfig::getTerrainTypePatternById(const std::string & id) const
|
|
||||||
|
const std::vector<TerrainViewPattern> * CTerrainViewPatternConfig::getTerrainTypePatternById(const std::string & id) const
|
||||||
{
|
{
|
||||||
auto it = terrainTypePatterns.find(id);
|
auto it = terrainTypePatterns.find(id);
|
||||||
assert(it != terrainTypePatterns.end());
|
assert(it != terrainTypePatterns.end());
|
||||||
return it->second;
|
return &(it->second);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CTerrainViewPatternConfig::flipPattern(TerrainViewPattern & pattern, int flip) const
|
||||||
|
{
|
||||||
|
//flip in place to avoid expensive constructor. Seriously.
|
||||||
|
|
||||||
|
if (flip == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//always flip horizontal
|
||||||
|
for (int i = 0; i < 3; ++i)
|
||||||
|
{
|
||||||
|
int y = i * 3;
|
||||||
|
std::swap(pattern.data[y], pattern.data[y + 2]);
|
||||||
|
}
|
||||||
|
//flip vertical only at 2nd step
|
||||||
|
if (flip == CMapOperation::FLIP_PATTERN_VERTICAL)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 3; ++i)
|
||||||
|
{
|
||||||
|
std::swap(pattern.data[i], pattern.data[6 + i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
CDrawTerrainOperation::CDrawTerrainOperation(CMap * map, const CTerrainSelection & terrainSel, ETerrainType terType, CRandomGenerator * gen)
|
CDrawTerrainOperation::CDrawTerrainOperation(CMap * map, const CTerrainSelection & terrainSel, ETerrainType terType, CRandomGenerator * gen)
|
||||||
: CMapOperation(map), terrainSel(terrainSel), terType(terType), gen(gen)
|
: CMapOperation(map), terrainSel(terrainSel), terType(terType), gen(gen)
|
||||||
{
|
{
|
||||||
@@ -643,8 +697,7 @@ void CDrawTerrainOperation::updateTerrainViews()
|
|||||||
{
|
{
|
||||||
for(const auto & pos : invalidatedTerViews)
|
for(const auto & pos : invalidatedTerViews)
|
||||||
{
|
{
|
||||||
const auto & patterns =
|
const auto & patterns = VLC->terviewh->getTerrainViewPatternsForGroup(getTerrainGroup(map->getTile(pos).terType));
|
||||||
VLC->terviewh->getTerrainViewPatternsForGroup(getTerrainGroup(map->getTile(pos).terType));
|
|
||||||
|
|
||||||
// Detect a pattern which fits best
|
// Detect a pattern which fits best
|
||||||
int bestPattern = -1;
|
int bestPattern = -1;
|
||||||
@@ -652,7 +705,8 @@ void CDrawTerrainOperation::updateTerrainViews()
|
|||||||
for(int k = 0; k < patterns.size(); ++k)
|
for(int k = 0; k < patterns.size(); ++k)
|
||||||
{
|
{
|
||||||
const auto & pattern = patterns[k];
|
const auto & pattern = patterns[k];
|
||||||
valRslt = validateTerrainView(pos, pattern);
|
//(ETerrainGroup::ETerrainGroup terGroup, const std::string & id)
|
||||||
|
valRslt = validateTerrainView(pos, &pattern);
|
||||||
if(valRslt.result)
|
if(valRslt.result)
|
||||||
{
|
{
|
||||||
/*logGlobal->debugStream() << boost::format("Pattern detected at pos '%s': Pattern '%s', Flip '%i', Repl. '%s'.") %
|
/*logGlobal->debugStream() << boost::format("Pattern detected at pos '%s': Pattern '%s', Flip '%i', Repl. '%s'.") %
|
||||||
@@ -671,7 +725,7 @@ void CDrawTerrainOperation::updateTerrainViews()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get mapping
|
// Get mapping
|
||||||
const TerrainViewPattern & pattern = patterns[bestPattern];
|
const TerrainViewPattern & pattern = patterns[bestPattern].front();
|
||||||
std::pair<int, int> mapping;
|
std::pair<int, int> mapping;
|
||||||
if(valRslt.transitionReplacement.empty())
|
if(valRslt.transitionReplacement.empty())
|
||||||
{
|
{
|
||||||
@@ -717,16 +771,11 @@ ETerrainGroup::ETerrainGroup CDrawTerrainOperation::getTerrainGroup(ETerrainType
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CDrawTerrainOperation::ValidationResult CDrawTerrainOperation::validateTerrainView(const int3 & pos, const TerrainViewPattern & pattern, int recDepth /*= 0*/) const
|
CDrawTerrainOperation::ValidationResult CDrawTerrainOperation::validateTerrainView(const int3 & pos, const std::vector<TerrainViewPattern> * pattern, int recDepth /*= 0*/) const
|
||||||
{
|
{
|
||||||
//constructor for pattern object is very expensive, but we can't manipulate const object :(
|
|
||||||
|
|
||||||
auto flippedPattern = pattern; //TODO: store cached patterns in 4 positions to avoid very expensive construction
|
|
||||||
for(int flip = 0; flip < 4; ++flip)
|
for(int flip = 0; flip < 4; ++flip)
|
||||||
{
|
{
|
||||||
if (flip > 0)
|
auto valRslt = validateTerrainViewInner(pos, pattern->at(flip), recDepth);
|
||||||
flipPattern (flippedPattern, flip);
|
|
||||||
auto valRslt = validateTerrainViewInner(pos, flippedPattern, recDepth);
|
|
||||||
if(valRslt.result)
|
if(valRslt.result)
|
||||||
{
|
{
|
||||||
valRslt.flip = flip;
|
valRslt.flip = flip;
|
||||||
@@ -806,10 +855,11 @@ CDrawTerrainOperation::ValidationResult CDrawTerrainOperation::validateTerrainVi
|
|||||||
{
|
{
|
||||||
if(terType == centerTerType)
|
if(terType == centerTerType)
|
||||||
{
|
{
|
||||||
const auto & patternForRule = VLC->terviewh->getTerrainViewPatternById(getTerrainGroup(centerTerType), rule.name);
|
const auto & group = getTerrainGroup(centerTerType);
|
||||||
if(patternForRule)
|
const auto & patternForRule = VLC->terviewh->getTerrainViewPatternsById(group, rule.name);
|
||||||
|
if(auto p = patternForRule)
|
||||||
{
|
{
|
||||||
auto rslt = validateTerrainView(currentPos, *patternForRule, 1);
|
auto rslt = validateTerrainView(currentPos, &(*p), 1);
|
||||||
if(rslt.result) topPoints = std::max(topPoints, rule.points);
|
if(rslt.result) topPoints = std::max(topPoints, rule.points);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -906,31 +956,6 @@ bool CDrawTerrainOperation::isSandType(ETerrainType terType) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CDrawTerrainOperation::flipPattern(TerrainViewPattern & pattern, int flip) const
|
|
||||||
{
|
|
||||||
//flip in place to avoid expensive constructor. Seriously.
|
|
||||||
|
|
||||||
if(flip == 0)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//always flip horizontal
|
|
||||||
for(int i = 0; i < 3; ++i)
|
|
||||||
{
|
|
||||||
int y = i * 3;
|
|
||||||
std::swap(pattern.data[y], pattern.data[y + 2]);
|
|
||||||
}
|
|
||||||
//flip vertical only at 2nd step
|
|
||||||
if(flip == FLIP_PATTERN_VERTICAL)
|
|
||||||
{
|
|
||||||
for(int i = 0; i < 3; ++i)
|
|
||||||
{
|
|
||||||
std::swap(pattern.data[i], pattern.data[6 + i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CDrawTerrainOperation::invalidateTerrainViews(const int3 & centerPos)
|
void CDrawTerrainOperation::invalidateTerrainViews(const int3 & centerPos)
|
||||||
{
|
{
|
||||||
auto rect = extendTileAroundSafely(centerPos);
|
auto rect = extendTileAroundSafely(centerPos);
|
||||||
|
@@ -115,14 +115,14 @@ public:
|
|||||||
virtual void redo() = 0;
|
virtual void redo() = 0;
|
||||||
virtual std::string getLabel() const = 0; /// Returns a display-able name of the operation.
|
virtual std::string getLabel() const = 0; /// Returns a display-able name of the operation.
|
||||||
|
|
||||||
protected:
|
|
||||||
MapRect extendTileAround(const int3 & centerPos) const;
|
|
||||||
MapRect extendTileAroundSafely(const int3 & centerPos) const; /// doesn't exceed map size
|
|
||||||
|
|
||||||
static const int FLIP_PATTERN_HORIZONTAL = 1;
|
static const int FLIP_PATTERN_HORIZONTAL = 1;
|
||||||
static const int FLIP_PATTERN_VERTICAL = 2;
|
static const int FLIP_PATTERN_VERTICAL = 2;
|
||||||
static const int FLIP_PATTERN_BOTH = 3;
|
static const int FLIP_PATTERN_BOTH = 3;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
MapRect extendTileAround(const int3 & centerPos) const;
|
||||||
|
MapRect extendTileAroundSafely(const int3 & centerPos) const; /// doesn't exceed map size
|
||||||
|
|
||||||
CMap * map;
|
CMap * map;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -336,14 +336,16 @@ public:
|
|||||||
CTerrainViewPatternConfig();
|
CTerrainViewPatternConfig();
|
||||||
~CTerrainViewPatternConfig();
|
~CTerrainViewPatternConfig();
|
||||||
|
|
||||||
const std::vector<TerrainViewPattern> & getTerrainViewPatternsForGroup(ETerrainGroup::ETerrainGroup terGroup) const;
|
const std::vector<std::vector<TerrainViewPattern>> & getTerrainViewPatternsForGroup(ETerrainGroup::ETerrainGroup terGroup) const;
|
||||||
boost::optional<const TerrainViewPattern &> getTerrainViewPatternById(ETerrainGroup::ETerrainGroup terGroup, const std::string & id) const;
|
boost::optional<const TerrainViewPattern &> getTerrainViewPatternById(ETerrainGroup::ETerrainGroup terGroup, const std::string & id) const;
|
||||||
const TerrainViewPattern & getTerrainTypePatternById(const std::string & id) const;
|
boost::optional<const std::vector<TerrainViewPattern> &> getTerrainViewPatternsById(ETerrainGroup::ETerrainGroup terGroup, const std::string & id) const;
|
||||||
|
const std::vector<TerrainViewPattern> * getTerrainTypePatternById(const std::string & id) const;
|
||||||
ETerrainGroup::ETerrainGroup getTerrainGroup(const std::string & terGroup) const;
|
ETerrainGroup::ETerrainGroup getTerrainGroup(const std::string & terGroup) const;
|
||||||
|
void flipPattern(TerrainViewPattern & pattern, int flip) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::map<ETerrainGroup::ETerrainGroup, std::vector<TerrainViewPattern> > terrainViewPatterns;
|
std::map<ETerrainGroup::ETerrainGroup, std::vector<std::vector<TerrainViewPattern> > > terrainViewPatterns;
|
||||||
std::map<std::string, TerrainViewPattern> terrainTypePatterns;
|
std::map<std::string, std::vector<TerrainViewPattern>> terrainTypePatterns;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The CDrawTerrainOperation class draws a terrain area on the map.
|
/// The CDrawTerrainOperation class draws a terrain area on the map.
|
||||||
@@ -384,11 +386,10 @@ private:
|
|||||||
ETerrainGroup::ETerrainGroup getTerrainGroup(ETerrainType terType) const;
|
ETerrainGroup::ETerrainGroup getTerrainGroup(ETerrainType terType) const;
|
||||||
/// Validates the terrain view of the given position and with the given pattern. The first method wraps the
|
/// 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).
|
/// 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 validateTerrainView(const int3 & pos, const std::vector<TerrainViewPattern> * pattern, int recDepth = 0) const;
|
||||||
ValidationResult validateTerrainViewInner(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
|
/// Tests whether the given terrain type is a sand type. Sand types are: Water, Sand and Rock
|
||||||
bool isSandType(ETerrainType terType) const;
|
bool isSandType(ETerrainType terType) const;
|
||||||
void flipPattern(TerrainViewPattern & pattern, int flip) const;
|
|
||||||
|
|
||||||
CTerrainSelection terrainSel;
|
CTerrainSelection terrainSel;
|
||||||
ETerrainType terType;
|
ETerrainType terType;
|
||||||
|
Reference in New Issue
Block a user