| 997 | } |
| 998 | |
| 999 | static PaintResult paintArea(MapExtras::MapCache& map, const df::coord& pos1, const df::coord& pos2, |
| 1000 | const TileType& target, const TileType& match = TileType()) { |
| 1001 | df::coord minPos = df::coord(std::min(pos1.x, pos2.x), std::min(pos1.y, pos2.y), std::min(pos1.z, pos2.z)); |
| 1002 | df::coord maxPos = df::coord(std::max(pos1.x, pos2.x), std::max(pos1.y, pos2.y), std::max(pos1.z, pos2.z)); |
| 1003 | |
| 1004 | int totalAffectedCount = 0; |
| 1005 | int totalFilteredCount = 0; |
| 1006 | coord_vec skipList = coord_vec(); |
| 1007 | |
| 1008 | // Loop through the affected blocks |
| 1009 | for (int16_t z = minPos.z; z <= maxPos.z; z++) { |
| 1010 | for (int16_t blockX = (minPos.x >> 4) << 4; blockX <= maxPos.x; blockX += 16) { |
| 1011 | for (int16_t blockY = (minPos.y >> 4) << 4; blockY <= maxPos.y; blockY += 16) { |
| 1012 | MapExtras::Block* block = map.BlockAtTile(df::coord(blockX, blockY, z)); |
| 1013 | if (!block) |
| 1014 | continue; |
| 1015 | |
| 1016 | int16_t startX = std::max(minPos.x - blockX, 0); |
| 1017 | int16_t startY = std::max(minPos.y - blockY, 0); |
| 1018 | int16_t endX = std::min(maxPos.x - blockX, 15); |
| 1019 | int16_t endY = std::min(maxPos.y - blockY, 15); |
| 1020 | // Loop through the affected tiles in the block |
| 1021 | for (int16_t xOffset = startX; xOffset <= endX; xOffset++) { |
| 1022 | for (int16_t yOffset = startY; yOffset <= endY; yOffset++) { |
| 1023 | df::coord2d blockOffset = df::coord2d(xOffset, yOffset); |
| 1024 | |
| 1025 | df::tiletype source = block->tiletypeAt(blockOffset); |
| 1026 | df::tile_designation des = block->DesignationAt(blockOffset); |
| 1027 | df::tile_occupancy occ = block->OccupancyAt(blockOffset); |
| 1028 | |
| 1029 | // Stone painting operates on the base layer |
| 1030 | if (target.stone_material >= 0) |
| 1031 | source = block->baseTiletypeAt(blockOffset); |
| 1032 | |
| 1033 | t_matpair basemat = block->baseMaterialAt(blockOffset); |
| 1034 | |
| 1035 | if (!match.matches(source, des, occ, basemat)) { |
| 1036 | totalFilteredCount++; |
| 1037 | skipList.push_back(df::coord(blockX + xOffset, blockY + yOffset, z)); |
| 1038 | continue; |
| 1039 | } |
| 1040 | |
| 1041 | if (paintTileProcessing(block, blockOffset, target)) { |
| 1042 | totalAffectedCount++; |
| 1043 | } |
| 1044 | else { |
| 1045 | skipList.push_back(df::coord(blockX + xOffset, blockY + yOffset, z)); |
| 1046 | continue; |
| 1047 | } |
| 1048 | } |
| 1049 | } |
| 1050 | } |
| 1051 | } |
| 1052 | } |
| 1053 | |
| 1054 | return PaintResult{ |
| 1055 | .paintCount = totalAffectedCount + totalFilteredCount, |
| 1056 | .postWrite = [totalAffectedCount, skipList, target, pos1, pos2](MapExtras::MapCache& map) { |
no test coverage detected