mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	Implemented road transitions.
* untested * still unused
This commit is contained in:
		| @@ -255,6 +255,8 @@ | ||||
| 		<Unit filename="mapObjects/ObjectTemplate.h" /> | ||||
| 		<Unit filename="mapping/CCampaignHandler.cpp" /> | ||||
| 		<Unit filename="mapping/CCampaignHandler.h" /> | ||||
| 		<Unit filename="mapping/CDrawRoadsOperation.cpp" /> | ||||
| 		<Unit filename="mapping/CDrawRoadsOperation.h" /> | ||||
| 		<Unit filename="mapping/CMap.cpp" /> | ||||
| 		<Unit filename="mapping/CMap.h" /> | ||||
| 		<Unit filename="mapping/CMapEditManager.cpp" /> | ||||
|   | ||||
| @@ -11,7 +11,7 @@ | ||||
| #include "StdInc.h" | ||||
| #include "CDrawRoadsOperation.h" | ||||
|  | ||||
| const std::vector<CDrawRoadsOperation::RoadPattern> CDrawRoadsOperation::rules =  | ||||
| const std::vector<CDrawRoadsOperation::RoadPattern> CDrawRoadsOperation::patterns =  | ||||
| { | ||||
| 	//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(CMap * map, const CTerrainSelection & terrainSel, ERoadType::ERoadType roadType, CRandomGenerator * gen): | ||||
| 	CMapOperation(map),terrainSel(terrainSel), roadType(roadType), gen(gen) | ||||
| @@ -138,7 +153,21 @@ CDrawRoadsOperation::CDrawRoadsOperation(CMap * map, const CTerrainSelection & t | ||||
|  | ||||
| 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() | ||||
| @@ -156,3 +185,169 @@ std::string CDrawRoadsOperation::getLabel() const | ||||
| 	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 | ||||
| 	{ | ||||
| 		std::string rules[9]; | ||||
| 		std::string data[9]; | ||||
| 		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; | ||||
| 	ERoadType::ERoadType roadType; | ||||
|   | ||||
| @@ -133,6 +133,18 @@ std::string CMapOperation::getLabel() const | ||||
| 	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) | ||||
| { | ||||
|  | ||||
| @@ -968,16 +980,6 @@ CDrawTerrainOperation::InvalidTiles CDrawTerrainOperation::getInvalidTiles(const | ||||
| 	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 /*= ""*/) | ||||
| 	: result(result), transitionReplacement(transitionReplacement) | ||||
| { | ||||
|   | ||||
| @@ -113,7 +113,14 @@ public: | ||||
| 	virtual void redo() = 0; | ||||
| 	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; | ||||
| }; | ||||
|  | ||||
| @@ -330,8 +337,6 @@ private: | ||||
| 	void updateTerrainTypes(); | ||||
| 	void invalidateTerrainViews(const int3 & centerPos); | ||||
| 	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(); | ||||
| 	ETerrainGroup::ETerrainGroup getTerrainGroup(ETerrainType terType) const; | ||||
| @@ -343,10 +348,6 @@ private: | ||||
| 	bool isSandType(ETerrainType terType) 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; | ||||
| 	ETerrainType terType; | ||||
| 	CRandomGenerator * gen; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user