#include "ShipLayoutPreview.h" #include #include namespace { const int kCellSize = 8; const ModuleDef* findModuleDef(const std::vector& modules, const std::string& id) { for (const ModuleDef& def : modules) { if (def.id == id) { return &def; } } return nullptr; } std::vector rotateMaskCW(const std::vector& grid) { if (grid.empty()) { return {}; } const int srcH = static_cast(grid.size()); int srcW = 0; for (const std::string& row : grid) { const int w = static_cast(row.size()); if (w > srcW) { srcW = w; } } const int dstW = srcH; const int dstH = srcW; std::vector dst(dstH, std::string(dstW, 'X')); for (int row = 0; row < srcH; ++row) { for (int col = 0; col < srcW; ++col) { const char ch = (col < static_cast(grid[row].size())) ? grid[row][col] : 'X'; dst[col][srcH - 1 - row] = ch; } } return dst; } std::vector rotateMask(const std::vector& mask, Rotation rotation) { int steps = 0; switch (rotation) { case Rotation::East: steps = 0; break; case Rotation::South: steps = 1; break; case Rotation::West: steps = 2; break; case Rotation::North: steps = 3; break; } std::vector result = mask; for (int i = 0; i < steps; ++i) { result = rotateMaskCW(result); } return result; } } // namespace ShipLayoutPreview::ShipLayoutPreview(QWidget* parent) : QWidget(parent) , m_modules(nullptr) , m_rows(0) , m_cols(0) { } void ShipLayoutPreview::clear() { m_grid.clear(); m_placedModules.clear(); m_modules = nullptr; m_rows = 0; m_cols = 0; setFixedSize(0, 0); update(); } void ShipLayoutPreview::setShipAndLayout(const std::vector& shipLayout, const ShipLayoutConfig& layout, const std::vector* modules) { m_modules = modules; m_placedModules = layout.placedModules; m_rows = static_cast(shipLayout.size()); m_cols = 0; for (const std::string& row : shipLayout) { const int w = static_cast(row.size()); if (w > m_cols) { m_cols = w; } } m_grid.assign(m_rows, std::vector(m_cols, {false, -1})); for (int r = 0; r < m_rows; ++r) { for (int c = 0; c < static_cast(shipLayout[r].size()); ++c) { if (shipLayout[r][c] == 'O') { m_grid[r][c].buildable = true; } } } for (int i = 0; i < static_cast(m_placedModules.size()); ++i) { const PlacedModule& pm = m_placedModules[i]; const ModuleDef* def = findModuleDef(*m_modules, pm.moduleId); if (!def) { continue; } const std::vector rotated = rotateMask(def->surfaceMask, pm.rotation); for (int mr = 0; mr < static_cast(rotated.size()); ++mr) { for (int mc = 0; mc < static_cast(rotated[mr].size()); ++mc) { if (rotated[mr][mc] != 'O') { continue; } const int gr = pm.position.y() + mr; const int gc = pm.position.x() + mc; if (gr >= 0 && gr < m_rows && gc >= 0 && gc < m_cols) { m_grid[gr][gc].moduleIndex = i; } } } } setFixedSize(m_cols * kCellSize, m_rows * kCellSize); update(); } void ShipLayoutPreview::paintEvent(QPaintEvent* /*event*/) { if (m_rows == 0 || m_cols == 0) { return; } QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing, false); for (int r = 0; r < m_rows; ++r) { for (int c = 0; c < m_cols; ++c) { const QRect cellRect(c * kCellSize, r * kCellSize, kCellSize, kCellSize); const CellInfo& cell = m_grid[r][c]; if (!cell.buildable) { painter.fillRect(cellRect, Qt::black); } else if (cell.moduleIndex >= 0) { const PlacedModule& pm = m_placedModules[cell.moduleIndex]; const ModuleDef* def = findModuleDef(*m_modules, pm.moduleId); QColor color(Qt::gray); if (def) { color = QColor(QString::fromStdString(def->fillColor)); } painter.fillRect(cellRect, color); } else { painter.fillRect(cellRect, Qt::white); } painter.setPen(QColor(128, 128, 128)); painter.drawRect(cellRect); } } }