mirror of
https://github.com/vcmi/vcmi.git
synced 2025-06-23 00:28:08 +02:00
Implemented road transitions.
* untested * still unused
This commit is contained in:
@ -255,6 +255,8 @@
|
|||||||
<Unit filename="mapObjects/ObjectTemplate.h" />
|
<Unit filename="mapObjects/ObjectTemplate.h" />
|
||||||
<Unit filename="mapping/CCampaignHandler.cpp" />
|
<Unit filename="mapping/CCampaignHandler.cpp" />
|
||||||
<Unit filename="mapping/CCampaignHandler.h" />
|
<Unit filename="mapping/CCampaignHandler.h" />
|
||||||
|
<Unit filename="mapping/CDrawRoadsOperation.cpp" />
|
||||||
|
<Unit filename="mapping/CDrawRoadsOperation.h" />
|
||||||
<Unit filename="mapping/CMap.cpp" />
|
<Unit filename="mapping/CMap.cpp" />
|
||||||
<Unit filename="mapping/CMap.h" />
|
<Unit filename="mapping/CMap.h" />
|
||||||
<Unit filename="mapping/CMapEditManager.cpp" />
|
<Unit filename="mapping/CMapEditManager.cpp" />
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
#include "StdInc.h"
|
#include "StdInc.h"
|
||||||
#include "CDrawRoadsOperation.h"
|
#include "CDrawRoadsOperation.h"
|
||||||
|
|
||||||
const std::vector<CDrawRoadsOperation::RoadPattern> CDrawRoadsOperation::rules =
|
const std::vector<CDrawRoadsOperation::RoadPattern> CDrawRoadsOperation::patterns =
|
||||||
{
|
{
|
||||||
//single tile. fallback patern
|
//single tile. fallback patern
|
||||||
{
|
{
|
||||||
@ -129,6 +129,21 @@ const std::vector<CDrawRoadsOperation::RoadPattern> CDrawRoadsOperation::rules =
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static bool ruleIsNone(const std::string & rule)
|
||||||
|
{
|
||||||
|
return rule == "-";
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool ruleIsSomething(const std::string & rule)
|
||||||
|
{
|
||||||
|
return rule == "+";
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool ruleIsAny(const std::string & rule)
|
||||||
|
{
|
||||||
|
return rule == "?";
|
||||||
|
}
|
||||||
|
|
||||||
///CDrawRoadsOperation
|
///CDrawRoadsOperation
|
||||||
CDrawRoadsOperation::CDrawRoadsOperation(CMap * map, const CTerrainSelection & terrainSel, ERoadType::ERoadType roadType, CRandomGenerator * gen):
|
CDrawRoadsOperation::CDrawRoadsOperation(CMap * map, const CTerrainSelection & terrainSel, ERoadType::ERoadType roadType, CRandomGenerator * gen):
|
||||||
CMapOperation(map),terrainSel(terrainSel), roadType(roadType), gen(gen)
|
CMapOperation(map),terrainSel(terrainSel), roadType(roadType), gen(gen)
|
||||||
@ -138,7 +153,21 @@ CDrawRoadsOperation::CDrawRoadsOperation(CMap * map, const CTerrainSelection & t
|
|||||||
|
|
||||||
void CDrawRoadsOperation::execute()
|
void CDrawRoadsOperation::execute()
|
||||||
{
|
{
|
||||||
|
std::set<int3> invalidated;
|
||||||
|
|
||||||
|
for(const auto & pos : terrainSel.getSelectedItems())
|
||||||
|
{
|
||||||
|
auto & tile = map->getTile(pos);
|
||||||
|
tile.roadType = roadType;
|
||||||
|
|
||||||
|
auto rect = extendTileAroundSafely(pos);
|
||||||
|
rect.forEach([&invalidated](const int3 & pos)
|
||||||
|
{
|
||||||
|
invalidated.insert(pos);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
updateTiles(invalidated);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CDrawRoadsOperation::undo()
|
void CDrawRoadsOperation::undo()
|
||||||
@ -156,3 +185,169 @@ std::string CDrawRoadsOperation::getLabel() const
|
|||||||
return "Draw Roads";
|
return "Draw Roads";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CDrawRoadsOperation::canApplyPattern(const RoadPattern & pattern) const
|
||||||
|
{
|
||||||
|
//TODO: this method should be virtual for river support
|
||||||
|
return pattern.roadMapping.first >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CDrawRoadsOperation::flipPattern(RoadPattern& pattern, int flip) const
|
||||||
|
{
|
||||||
|
//todo: use cashing here and also in terrain patterns
|
||||||
|
|
||||||
|
if(flip == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(flip == FLIP_PATTERN_HORIZONTAL || flip == FLIP_PATTERN_BOTH)
|
||||||
|
{
|
||||||
|
for(int i = 0; i < 3; ++i)
|
||||||
|
{
|
||||||
|
int y = i * 3;
|
||||||
|
std::swap(pattern.data[y], pattern.data[y + 2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(flip == FLIP_PATTERN_VERTICAL || flip == FLIP_PATTERN_BOTH)
|
||||||
|
{
|
||||||
|
for(int i = 0; i < 3; ++i)
|
||||||
|
{
|
||||||
|
std::swap(pattern.data[i], pattern.data[6 + i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool CDrawRoadsOperation::needUpdateTile(const TerrainTile & tile) const
|
||||||
|
{
|
||||||
|
return tile.roadType != ERoadType::NO_ROAD; //TODO: this method should be virtual for river support
|
||||||
|
}
|
||||||
|
|
||||||
|
void CDrawRoadsOperation::updateTiles(std::set<int3> & invalidated)
|
||||||
|
{
|
||||||
|
for(int3 coord : invalidated)
|
||||||
|
{
|
||||||
|
TerrainTile & tile = map->getTile(coord);
|
||||||
|
ValidationResult result(false);
|
||||||
|
|
||||||
|
if(!needUpdateTile(tile))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int bestPattern = -1;
|
||||||
|
|
||||||
|
for(int k = 0; k < patterns.size(); ++k)
|
||||||
|
{
|
||||||
|
result = validateTile(patterns[k], coord);
|
||||||
|
|
||||||
|
if(result.result)
|
||||||
|
{
|
||||||
|
bestPattern = k;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(bestPattern != -1)
|
||||||
|
{
|
||||||
|
updateTile(tile, patterns[bestPattern], result.flip);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
bool CDrawRoadsOperation::tileHasSomething(const int3& pos) const
|
||||||
|
{
|
||||||
|
//TODO: this method should be virtual for river support
|
||||||
|
|
||||||
|
return map->getTile(pos).roadType != ERoadType::NO_ROAD;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CDrawRoadsOperation::updateTile(TerrainTile & tile, const RoadPattern & pattern, const int flip)
|
||||||
|
{
|
||||||
|
//TODO: this method should be virtual for river support
|
||||||
|
|
||||||
|
std::pair<int, int> mapping = pattern.roadMapping;
|
||||||
|
|
||||||
|
tile.roadDir = gen->nextInt(mapping.first, mapping.second);
|
||||||
|
tile.extTileFlags = (tile.extTileFlags & 0xCF) | (flip << 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
CDrawRoadsOperation::ValidationResult CDrawRoadsOperation::validateTile(const RoadPattern & pattern, const int3 & pos)
|
||||||
|
{
|
||||||
|
ValidationResult result(false);
|
||||||
|
|
||||||
|
if(!canApplyPattern(pattern))
|
||||||
|
return result;
|
||||||
|
|
||||||
|
|
||||||
|
for(int flip = 0; flip < 4; ++flip)
|
||||||
|
{
|
||||||
|
if((flip == FLIP_PATTERN_BOTH) && !(pattern.hasHFlip && pattern.hasVFlip))
|
||||||
|
continue;
|
||||||
|
if((flip == FLIP_PATTERN_HORIZONTAL) && !pattern.hasHFlip)
|
||||||
|
continue;
|
||||||
|
if((flip == FLIP_PATTERN_VERTICAL) && !(pattern.hasVFlip))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
RoadPattern flipped = pattern;
|
||||||
|
|
||||||
|
flipPattern(flipped, flip);
|
||||||
|
|
||||||
|
bool validated = true;
|
||||||
|
|
||||||
|
for(int i = 0; i < 9; ++i)
|
||||||
|
{
|
||||||
|
if(4 == i)
|
||||||
|
continue;
|
||||||
|
int cx = pos.x + (i % 3) - 1;
|
||||||
|
int cy = pos.y + (i / 3) - 1;
|
||||||
|
|
||||||
|
int3 currentPos(cx, cy, pos.z);
|
||||||
|
|
||||||
|
bool hasSomething;
|
||||||
|
|
||||||
|
if(!map->isInTheMap(currentPos))
|
||||||
|
{
|
||||||
|
hasSomething = true; //road/river can go out of map
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hasSomething = tileHasSomething(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ruleIsSomething(flipped.data[i]))
|
||||||
|
{
|
||||||
|
if(!hasSomething)
|
||||||
|
{
|
||||||
|
validated = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(ruleIsNone(flipped.data[i]))
|
||||||
|
{
|
||||||
|
if(hasSomething)
|
||||||
|
{
|
||||||
|
validated = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert(ruleIsAny(flipped.data[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if(validated)
|
||||||
|
{
|
||||||
|
result.result = true;
|
||||||
|
result.flip = flip;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -27,12 +27,30 @@ private:
|
|||||||
|
|
||||||
struct RoadPattern
|
struct RoadPattern
|
||||||
{
|
{
|
||||||
std::string rules[9];
|
std::string data[9];
|
||||||
std::pair<int, int> roadMapping, riverMapping;
|
std::pair<int, int> roadMapping, riverMapping;
|
||||||
bool hasHFlip, hasBFlip;
|
bool hasHFlip, hasVFlip;
|
||||||
};
|
};
|
||||||
|
|
||||||
static const std::vector<RoadPattern> rules;
|
struct ValidationResult
|
||||||
|
{
|
||||||
|
ValidationResult(bool result): result(result), flip(0){};
|
||||||
|
bool result;
|
||||||
|
int flip;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const std::vector<RoadPattern> patterns;
|
||||||
|
|
||||||
|
void flipPattern(RoadPattern & pattern, int flip) const;
|
||||||
|
|
||||||
|
void updateTiles(std::set<int3> & invalidated);
|
||||||
|
|
||||||
|
ValidationResult validateTile(const RoadPattern & pattern, const int3 & pos);
|
||||||
|
void updateTile(TerrainTile & tile, const RoadPattern & pattern, const int flip);
|
||||||
|
|
||||||
|
bool canApplyPattern(const RoadPattern & pattern) const;
|
||||||
|
bool needUpdateTile(const TerrainTile & tile) const;
|
||||||
|
bool tileHasSomething(const int3 & pos) const;
|
||||||
|
|
||||||
CTerrainSelection terrainSel;
|
CTerrainSelection terrainSel;
|
||||||
ERoadType::ERoadType roadType;
|
ERoadType::ERoadType roadType;
|
||||||
|
@ -133,6 +133,18 @@ std::string CMapOperation::getLabel() const
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
MapRect CMapOperation::extendTileAround(const int3 & centerPos) const
|
||||||
|
{
|
||||||
|
return MapRect(int3(centerPos.x - 1, centerPos.y - 1, centerPos.z), 3, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
MapRect CMapOperation::extendTileAroundSafely(const int3 & centerPos) const
|
||||||
|
{
|
||||||
|
return extendTileAround(centerPos) & MapRect(int3(0, 0, centerPos.z), map->width, map->height);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
CMapUndoManager::CMapUndoManager() : undoRedoLimit(10)
|
CMapUndoManager::CMapUndoManager() : undoRedoLimit(10)
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -968,16 +980,6 @@ CDrawTerrainOperation::InvalidTiles CDrawTerrainOperation::getInvalidTiles(const
|
|||||||
return tiles;
|
return tiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
MapRect CDrawTerrainOperation::extendTileAround(const int3 & centerPos) const
|
|
||||||
{
|
|
||||||
return MapRect(int3(centerPos.x - 1, centerPos.y - 1, centerPos.z), 3, 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
MapRect CDrawTerrainOperation::extendTileAroundSafely(const int3 & centerPos) const
|
|
||||||
{
|
|
||||||
return extendTileAround(centerPos) & MapRect(int3(0, 0, centerPos.z), map->width, map->height);
|
|
||||||
}
|
|
||||||
|
|
||||||
CDrawTerrainOperation::ValidationResult::ValidationResult(bool result, const std::string & transitionReplacement /*= ""*/)
|
CDrawTerrainOperation::ValidationResult::ValidationResult(bool result, const std::string & transitionReplacement /*= ""*/)
|
||||||
: result(result), transitionReplacement(transitionReplacement)
|
: result(result), transitionReplacement(transitionReplacement)
|
||||||
{
|
{
|
||||||
|
@ -114,6 +114,13 @@ public:
|
|||||||
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:
|
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_VERTICAL = 2;
|
||||||
|
static const int FLIP_PATTERN_BOTH = 3;
|
||||||
|
|
||||||
CMap * map;
|
CMap * map;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -330,8 +337,6 @@ private:
|
|||||||
void updateTerrainTypes();
|
void updateTerrainTypes();
|
||||||
void invalidateTerrainViews(const int3 & centerPos);
|
void invalidateTerrainViews(const int3 & centerPos);
|
||||||
InvalidTiles getInvalidTiles(const int3 & centerPos) const;
|
InvalidTiles getInvalidTiles(const int3 & centerPos) const;
|
||||||
MapRect extendTileAround(const int3 & centerPos) const;
|
|
||||||
MapRect extendTileAroundSafely(const int3 & centerPos) const; /// doesn't exceed map size
|
|
||||||
|
|
||||||
void updateTerrainViews();
|
void updateTerrainViews();
|
||||||
ETerrainGroup::ETerrainGroup getTerrainGroup(ETerrainType terType) const;
|
ETerrainGroup::ETerrainGroup getTerrainGroup(ETerrainType terType) const;
|
||||||
@ -343,10 +348,6 @@ private:
|
|||||||
bool isSandType(ETerrainType terType) const;
|
bool isSandType(ETerrainType terType) const;
|
||||||
void flipPattern(TerrainViewPattern & pattern, int flip) const;
|
void flipPattern(TerrainViewPattern & pattern, int flip) const;
|
||||||
|
|
||||||
static const int FLIP_PATTERN_HORIZONTAL = 1;
|
|
||||||
static const int FLIP_PATTERN_VERTICAL = 2;
|
|
||||||
static const int FLIP_PATTERN_BOTH = 3;
|
|
||||||
|
|
||||||
CTerrainSelection terrainSel;
|
CTerrainSelection terrainSel;
|
||||||
ETerrainType terType;
|
ETerrainType terType;
|
||||||
CRandomGenerator * gen;
|
CRandomGenerator * gen;
|
||||||
|
Reference in New Issue
Block a user