From 5cfabca99f2bbb711dc278c9883ba656a4f73b43 Mon Sep 17 00:00:00 2001 From: Opuszek Date: Wed, 29 Oct 2025 13:39:37 +0100 Subject: [PATCH 1/2] #mapeditor Implements undo and redo operation for drawing terrain --- lib/mapping/CMapOperation.cpp | 28 ++++++++++++++++++++++------ lib/mapping/CMapOperation.h | 4 +++- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/lib/mapping/CMapOperation.cpp b/lib/mapping/CMapOperation.cpp index 2cf46f200..d161f750d 100644 --- a/lib/mapping/CMapOperation.cpp +++ b/lib/mapping/CMapOperation.cpp @@ -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()); diff --git a/lib/mapping/CMapOperation.h b/lib/mapping/CMapOperation.h index 1e6d1ad8e..b9d2e3e1d 100644 --- a/lib/mapping/CMapOperation.h +++ b/lib/mapping/CMapOperation.h @@ -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 formerState; int decorationsPercentage; vstd::RNG* gen; std::set invalidatedTerViews; From a1499af9addc81848da6d966fb4b90a5bbd7b924 Mon Sep 17 00:00:00 2001 From: Opuszek Date: Wed, 29 Oct 2025 14:23:54 +0100 Subject: [PATCH 2/2] #mapeditor Implements undo and redo operation for drawing roads and rivers --- lib/mapping/CDrawRoadsOperation.cpp | 76 ++++++++++++++++++++--------- lib/mapping/CDrawRoadsOperation.h | 36 ++++++++------ 2 files changed, 76 insertions(+), 36 deletions(-) diff --git a/lib/mapping/CDrawRoadsOperation.cpp b/lib/mapping/CDrawRoadsOperation.cpp index 32625d9c0..cbe0997b3 100644 --- a/lib/mapping/CDrawRoadsOperation.cpp +++ b/lib/mapping/CDrawRoadsOperation.cpp @@ -20,7 +20,8 @@ VCMI_LIB_NAMESPACE_BEGIN -const std::vector CDrawLinesOperation::patterns = +template +const std::vector::LinePattern> CDrawLinesOperation::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 +CDrawLinesOperation::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 +void CDrawLinesOperation::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); + } + + drawLines(terrainSel, lineType); } -void CDrawLinesOperation::execute() +template +void CDrawLinesOperation::drawLines(CTerrainSelection selection, T type) { std::set 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 +void CDrawLinesOperation::undo() { - //TODO + for (auto const& typeToSelection : formerState) + { + drawLines(typeToSelection.second, typeToSelection.first); + } } -void CDrawLinesOperation::redo() +template +void CDrawLinesOperation::redo() { - //TODO + drawLines(terrainSel, lineType); } -void CDrawLinesOperation::flipPattern(LinePattern& pattern, int flip) const +template +void CDrawLinesOperation::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 & invalidated) +template +void CDrawLinesOperation::updateTiles(std::set & invalidated) { for(const int3 & coord : invalidated) { @@ -264,7 +285,8 @@ void CDrawLinesOperation::updateTiles(std::set & invalidated) } } -CDrawLinesOperation::ValidationResult CDrawLinesOperation::validateTile(const LinePattern & pattern, const int3 & pos) +template +typename CDrawLinesOperation::ValidationResult CDrawLinesOperation::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 diff --git a/lib/mapping/CDrawRoadsOperation.h b/lib/mapping/CDrawRoadsOperation.h index 7e9ea754d..21f4ca4ed 100644 --- a/lib/mapping/CDrawRoadsOperation.h +++ b/lib/mapping/CDrawRoadsOperation.h @@ -16,7 +16,7 @@ VCMI_LIB_NAMESPACE_BEGIN struct TerrainTile; -class CDrawLinesOperation : public CMapOperation +template class CDrawLinesOperation : public CMapOperation { public: void execute() override; @@ -41,14 +41,15 @@ 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 patterns; void flipPattern(LinePattern & pattern, int flip) const; @@ -58,38 +59,45 @@ protected: ValidationResult validateTile(const LinePattern & pattern, const int3 & pos); CTerrainSelection terrainSel; + T lineType; vstd::RNG * gen; + std::map formerState; + +private: + void drawLines(CTerrainSelection selection, T type); }; -class CDrawRoadsOperation : public CDrawLinesOperation +class CDrawRoadsOperation : public CDrawLinesOperation { 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 { 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;