mirror of
https://github.com/vcmi/vcmi.git
synced 2025-11-23 22:37:55 +02:00
Merge pull request #6261 from Opuszek/mapeditor_fix_rivers
Implements undo and redo operations for terrain/river/road changes in map editor
This commit is contained in:
@@ -20,7 +20,8 @@
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
const std::vector<CDrawLinesOperation::LinePattern> CDrawLinesOperation::patterns =
|
||||
template <typename T>
|
||||
const std::vector<typename CDrawLinesOperation<T>::LinePattern> CDrawLinesOperation<T>::patterns =
|
||||
{
|
||||
//single tile. fall-back pattern
|
||||
{
|
||||
@@ -156,34 +157,47 @@ static bool ruleIsAny(const std::string & rule)
|
||||
#endif
|
||||
|
||||
///CDrawLinesOperation
|
||||
CDrawLinesOperation::CDrawLinesOperation(CMap * map, CTerrainSelection terrainSel, vstd::RNG * gen):
|
||||
template <typename T>
|
||||
CDrawLinesOperation<T>::CDrawLinesOperation(CMap * map, CTerrainSelection terrainSel, T lineType, vstd::RNG * gen):
|
||||
CMapOperation(map),
|
||||
terrainSel(std::move(terrainSel)),
|
||||
lineType(lineType),
|
||||
gen(gen)
|
||||
{
|
||||
}
|
||||
|
||||
///CDrawRoadsOperation
|
||||
CDrawRoadsOperation::CDrawRoadsOperation(CMap * map, const CTerrainSelection & terrainSel, RoadId roadType, vstd::RNG * gen):
|
||||
CDrawLinesOperation(map, terrainSel,gen),
|
||||
roadType(roadType)
|
||||
{
|
||||
}
|
||||
CDrawLinesOperation(map, terrainSel,roadType, gen)
|
||||
{}
|
||||
|
||||
///CDrawRiversOperation
|
||||
CDrawRiversOperation::CDrawRiversOperation(CMap * map, const CTerrainSelection & terrainSel, RiverId riverType, vstd::RNG * gen):
|
||||
CDrawLinesOperation(map, terrainSel, gen),
|
||||
riverType(riverType)
|
||||
CDrawLinesOperation(map, terrainSel, riverType, gen)
|
||||
{}
|
||||
|
||||
template <typename T>
|
||||
void CDrawLinesOperation<T>::execute()
|
||||
{
|
||||
for(const auto & pos : terrainSel.getSelectedItems())
|
||||
{
|
||||
auto identifier = getIdentifier(map->getTile(pos));
|
||||
if (formerState.find(identifier) == formerState.end())
|
||||
formerState.insert({identifier, CTerrainSelection(terrainSel.getMap())});
|
||||
formerState.at(identifier).select(pos);
|
||||
}
|
||||
|
||||
void CDrawLinesOperation::execute()
|
||||
drawLines(terrainSel, lineType);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void CDrawLinesOperation<T>::drawLines(CTerrainSelection selection, T type)
|
||||
{
|
||||
std::set<int3> invalidated;
|
||||
|
||||
for(const auto & pos : terrainSel.getSelectedItems())
|
||||
for(const auto & pos : selection.getSelectedItems())
|
||||
{
|
||||
executeTile(map->getTile(pos));
|
||||
executeTile(map->getTile(pos), type);
|
||||
|
||||
auto rect = extendTileAroundSafely(pos);
|
||||
rect.forEach([&invalidated](const int3 & pos)
|
||||
@@ -195,17 +209,23 @@ void CDrawLinesOperation::execute()
|
||||
updateTiles(invalidated);
|
||||
}
|
||||
|
||||
void CDrawLinesOperation::undo()
|
||||
template <typename T>
|
||||
void CDrawLinesOperation<T>::undo()
|
||||
{
|
||||
//TODO
|
||||
for (auto const& typeToSelection : formerState)
|
||||
{
|
||||
drawLines(typeToSelection.second, typeToSelection.first);
|
||||
}
|
||||
}
|
||||
|
||||
void CDrawLinesOperation::redo()
|
||||
template <typename T>
|
||||
void CDrawLinesOperation<T>::redo()
|
||||
{
|
||||
//TODO
|
||||
drawLines(terrainSel, lineType);
|
||||
}
|
||||
|
||||
void CDrawLinesOperation::flipPattern(LinePattern& pattern, int flip) const
|
||||
template <typename T>
|
||||
void CDrawLinesOperation<T>::flipPattern(LinePattern& pattern, int flip) const
|
||||
{
|
||||
//todo: use cashing here and also in terrain patterns
|
||||
|
||||
@@ -233,7 +253,8 @@ void CDrawLinesOperation::flipPattern(LinePattern& pattern, int flip) const
|
||||
}
|
||||
}
|
||||
|
||||
void CDrawLinesOperation::updateTiles(std::set<int3> & invalidated)
|
||||
template <typename T>
|
||||
void CDrawLinesOperation<T>::updateTiles(std::set<int3> & invalidated)
|
||||
{
|
||||
for(const int3 & coord : invalidated)
|
||||
{
|
||||
@@ -264,7 +285,8 @@ void CDrawLinesOperation::updateTiles(std::set<int3> & invalidated)
|
||||
}
|
||||
}
|
||||
|
||||
CDrawLinesOperation::ValidationResult CDrawLinesOperation::validateTile(const LinePattern & pattern, const int3 & pos)
|
||||
template <typename T>
|
||||
typename CDrawLinesOperation<T>::ValidationResult CDrawLinesOperation<T>::validateTile(const LinePattern & pattern, const int3 & pos)
|
||||
{
|
||||
ValidationResult result(false);
|
||||
|
||||
@@ -342,14 +364,14 @@ std::string CDrawRiversOperation::getLabel() const
|
||||
return "Draw Rivers";
|
||||
}
|
||||
|
||||
void CDrawRoadsOperation::executeTile(TerrainTile & tile)
|
||||
void CDrawRoadsOperation::executeTile(TerrainTile & tile, RoadId type)
|
||||
{
|
||||
tile.roadType = roadType;
|
||||
tile.roadType = type;
|
||||
}
|
||||
|
||||
void CDrawRiversOperation::executeTile(TerrainTile & tile)
|
||||
void CDrawRiversOperation::executeTile(TerrainTile & tile, RiverId type)
|
||||
{
|
||||
tile.riverType = riverType;
|
||||
tile.riverType = type;
|
||||
}
|
||||
|
||||
bool CDrawRoadsOperation::canApplyPattern(const LinePattern & pattern) const
|
||||
@@ -398,4 +420,14 @@ void CDrawRiversOperation::updateTile(TerrainTile & tile, const LinePattern & pa
|
||||
tile.extTileFlags = (tile.extTileFlags & 0b00111111) | (flip << 2);
|
||||
}
|
||||
|
||||
RiverId CDrawRiversOperation::getIdentifier(TerrainTile & tile) const
|
||||
{
|
||||
return tile.riverType;
|
||||
}
|
||||
|
||||
RoadId CDrawRoadsOperation::getIdentifier(TerrainTile & tile) const
|
||||
{
|
||||
return tile.roadType;
|
||||
}
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
||||
@@ -16,7 +16,7 @@ VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
struct TerrainTile;
|
||||
|
||||
class CDrawLinesOperation : public CMapOperation
|
||||
template <typename T> class CDrawLinesOperation : public CMapOperation
|
||||
{
|
||||
public:
|
||||
void execute() override;
|
||||
@@ -41,13 +41,14 @@ protected:
|
||||
int flip;
|
||||
};
|
||||
|
||||
CDrawLinesOperation(CMap * map, CTerrainSelection terrainSel, vstd::RNG * gen);
|
||||
CDrawLinesOperation(CMap * map, CTerrainSelection terrainSel, T lineType, vstd::RNG * gen);
|
||||
|
||||
virtual void executeTile(TerrainTile & tile) = 0;
|
||||
virtual bool canApplyPattern(const CDrawLinesOperation::LinePattern & pattern) const = 0;
|
||||
virtual void executeTile(TerrainTile & tile, T type) = 0;
|
||||
virtual bool canApplyPattern(const LinePattern & pattern) const = 0;
|
||||
virtual bool needUpdateTile(const TerrainTile & tile) const = 0;
|
||||
virtual bool tileHasSomething(const int3 & pos) const = 0;
|
||||
virtual void updateTile(TerrainTile & tile, const CDrawLinesOperation::LinePattern & pattern, const int flip) = 0;
|
||||
virtual void updateTile(TerrainTile & tile, const LinePattern & pattern, const int flip) = 0;
|
||||
virtual T getIdentifier(TerrainTile & tile) const = 0;
|
||||
|
||||
static const std::vector<LinePattern> patterns;
|
||||
|
||||
@@ -58,38 +59,45 @@ protected:
|
||||
ValidationResult validateTile(const LinePattern & pattern, const int3 & pos);
|
||||
|
||||
CTerrainSelection terrainSel;
|
||||
T lineType;
|
||||
vstd::RNG * gen;
|
||||
std::map<T, CTerrainSelection> formerState;
|
||||
|
||||
private:
|
||||
void drawLines(CTerrainSelection selection, T type);
|
||||
};
|
||||
|
||||
class CDrawRoadsOperation : public CDrawLinesOperation
|
||||
class CDrawRoadsOperation : public CDrawLinesOperation<RoadId>
|
||||
{
|
||||
public:
|
||||
CDrawRoadsOperation(CMap * map, const CTerrainSelection & terrainSel, RoadId roadType, vstd::RNG * gen);
|
||||
std::string getLabel() const override;
|
||||
|
||||
protected:
|
||||
void executeTile(TerrainTile & tile) override;
|
||||
bool canApplyPattern(const CDrawLinesOperation::LinePattern & pattern) const override;
|
||||
void executeTile(TerrainTile & tile, RoadId type) override;
|
||||
bool canApplyPattern(const LinePattern & pattern) const override;
|
||||
bool needUpdateTile(const TerrainTile & tile) const override;
|
||||
bool tileHasSomething(const int3 & pos) const override;
|
||||
void updateTile(TerrainTile & tile, const CDrawLinesOperation::LinePattern & pattern, const int flip) override;
|
||||
void updateTile(TerrainTile & tile, const LinePattern & pattern, const int flip) override;
|
||||
RoadId getIdentifier(TerrainTile & tile) const override;
|
||||
|
||||
private:
|
||||
RoadId roadType;
|
||||
};
|
||||
|
||||
class CDrawRiversOperation : public CDrawLinesOperation
|
||||
class CDrawRiversOperation : public CDrawLinesOperation<RiverId>
|
||||
{
|
||||
public:
|
||||
CDrawRiversOperation(CMap * map, const CTerrainSelection & terrainSel, RiverId roadType, vstd::RNG * gen);
|
||||
std::string getLabel() const override;
|
||||
|
||||
protected:
|
||||
void executeTile(TerrainTile & tile) override;
|
||||
bool canApplyPattern(const CDrawLinesOperation::LinePattern & pattern) const override;
|
||||
void executeTile(TerrainTile & tile, RiverId type) override;
|
||||
bool canApplyPattern(const LinePattern & pattern) const override;
|
||||
bool needUpdateTile(const TerrainTile & tile) const override;
|
||||
bool tileHasSomething(const int3 & pos) const override;
|
||||
void updateTile(TerrainTile & tile, const CDrawLinesOperation::LinePattern & pattern, const int flip) override;
|
||||
void updateTile(TerrainTile & tile, const LinePattern & pattern, const int flip) override;
|
||||
RiverId getIdentifier(TerrainTile & tile) const override;
|
||||
|
||||
private:
|
||||
RiverId riverType;
|
||||
|
||||
@@ -103,22 +103,38 @@ void CDrawTerrainOperation::execute()
|
||||
for(const auto & pos : terrainSel.getSelectedItems())
|
||||
{
|
||||
auto & tile = map->getTile(pos);
|
||||
tile.terrainType = terType;
|
||||
if (formerState.find(tile.terrainType) == formerState.end())
|
||||
formerState.insert({tile.terrainType, CTerrainSelection(terrainSel.getMap())});
|
||||
formerState.at(tile.terrainType).select(pos);
|
||||
}
|
||||
drawTerrain(terType, terrainSel);
|
||||
}
|
||||
|
||||
void CDrawTerrainOperation::drawTerrain(TerrainId terrainType, CTerrainSelection selection)
|
||||
{
|
||||
for(const auto & pos : selection.getSelectedItems())
|
||||
{
|
||||
auto & tile = map->getTile(pos);
|
||||
tile.terrainType = terrainType;
|
||||
invalidateTerrainViews(pos);
|
||||
}
|
||||
|
||||
updateTerrainTypes();
|
||||
updateTerrainTypes(selection);
|
||||
updateTerrainViews();
|
||||
invalidatedTerViews.clear();
|
||||
}
|
||||
|
||||
void CDrawTerrainOperation::undo()
|
||||
{
|
||||
//TODO
|
||||
for (auto const& typeToSelection : formerState)
|
||||
{
|
||||
drawTerrain(typeToSelection.first, typeToSelection.second);
|
||||
}
|
||||
}
|
||||
|
||||
void CDrawTerrainOperation::redo()
|
||||
{
|
||||
//TODO
|
||||
drawTerrain(terType, terrainSel);
|
||||
}
|
||||
|
||||
std::string CDrawTerrainOperation::getLabel() const
|
||||
@@ -126,9 +142,9 @@ std::string CDrawTerrainOperation::getLabel() const
|
||||
return "Draw Terrain";
|
||||
}
|
||||
|
||||
void CDrawTerrainOperation::updateTerrainTypes()
|
||||
void CDrawTerrainOperation::updateTerrainTypes(CTerrainSelection selection)
|
||||
{
|
||||
auto positions = terrainSel.getSelectedItems();
|
||||
auto positions = selection.getSelectedItems();
|
||||
while(!positions.empty())
|
||||
{
|
||||
const auto & centerPos = *(positions.begin());
|
||||
|
||||
@@ -94,7 +94,8 @@ private:
|
||||
InvalidTiles() : centerPosValid(false) { }
|
||||
};
|
||||
|
||||
void updateTerrainTypes();
|
||||
void drawTerrain(TerrainId terrain, CTerrainSelection selection);
|
||||
void updateTerrainTypes(CTerrainSelection selection);
|
||||
void invalidateTerrainViews(const int3 & centerPos);
|
||||
InvalidTiles getInvalidTiles(const int3 & centerPos) const;
|
||||
|
||||
@@ -106,6 +107,7 @@ private:
|
||||
|
||||
CTerrainSelection terrainSel;
|
||||
TerrainId terType;
|
||||
std::map<TerrainId, CTerrainSelection> formerState;
|
||||
int decorationsPercentage;
|
||||
vstd::RNG* gen;
|
||||
std::set<int3> invalidatedTerViews;
|
||||
|
||||
Reference in New Issue
Block a user