#include "unit_layer.h" #include "minimap_utils.h" #include #include #include namespace Game::Map::Minimap { void UnitLayer::init(int width, int height, float world_width, float world_height) { m_width = width; m_height = height; m_world_width = world_width; m_world_height = world_height; m_scale_x = static_cast(width - 1) / world_width; m_scale_y = static_cast(height - 1) / world_height; m_offset_x = world_width * 0.5F; m_offset_y = world_height * 0.5F; m_image = QImage(width, height, QImage::Format_RGBA8888); m_image.fill(Qt::transparent); } auto UnitLayer::world_to_pixel(float world_x, float world_z) const -> std::pair { const auto &orient = MinimapOrientation::instance(); const float rotated_x = world_x * orient.cos_yaw() - world_z * orient.sin_yaw(); const float rotated_z = world_x * orient.sin_yaw() + world_z * orient.cos_yaw(); const float px = (rotated_x + m_offset_x) * m_scale_x; const float py = (rotated_z + m_offset_y) * m_scale_y; return {px, py}; } void UnitLayer::update(const std::vector &markers) { update(markers, 0, nullptr, nullptr); } void UnitLayer::update(const std::vector &markers, int local_owner_id, const VisibilityCheckFn &visibility_check, const PlayerColorFn &player_color_fn) { if (m_image.isNull()) { return; } m_image.fill(Qt::transparent); if (markers.empty()) { return; } QPainter painter(&m_image); painter.setRenderHint(QPainter::Antialiasing, true); std::vector buildings; std::vector units; std::vector selected; for (const auto &marker : markers) { if (visibility_check && marker.owner_id != local_owner_id && local_owner_id > 0) { if (!visibility_check(marker.world_x, marker.world_z)) { continue; } } if (marker.is_selected) { selected.push_back(&marker); } else if (marker.is_building) { buildings.push_back(&marker); } else { units.push_back(&marker); } } for (const auto *marker : buildings) { const auto [px, py] = world_to_pixel(marker->world_x, marker->world_z); const auto colors = get_color_for_owner(marker->owner_id, player_color_fn); draw_building_marker(painter, px, py, colors, false); } for (const auto *marker : units) { const auto [px, py] = world_to_pixel(marker->world_x, marker->world_z); const auto colors = get_color_for_owner(marker->owner_id, player_color_fn); draw_unit_marker(painter, px, py, colors, false); } for (const auto *marker : selected) { const auto [px, py] = world_to_pixel(marker->world_x, marker->world_z); const auto colors = get_color_for_owner(marker->owner_id, player_color_fn); if (marker->is_building) { draw_building_marker(painter, px, py, colors, true); } else { draw_unit_marker(painter, px, py, colors, true); } } } auto UnitLayer::get_color_for_owner(int owner_id, const PlayerColorFn &player_color_fn) -> TeamColors::ColorSet { if (player_color_fn) { std::uint8_t r, g, b; if (player_color_fn(owner_id, r, g, b)) { return TeamColors::ColorSet{r, g, b, static_cast(r / 2), static_cast(g / 2), static_cast(b / 2)}; } } return TeamColors::get_color(owner_id); } void UnitLayer::draw_unit_marker(QPainter &painter, float px, float py, const TeamColors::ColorSet &colors, bool is_selected) { const QPointF center(static_cast(px), static_cast(py)); if (is_selected) { painter.setBrush(Qt::NoBrush); QPen glow_pen(QColor(TeamColors::SELECT_R, TeamColors::SELECT_G, TeamColors::SELECT_B, 200)); glow_pen.setWidthF(2.0); painter.setPen(glow_pen); painter.drawEllipse(center, m_unit_radius + 2.0, m_unit_radius + 2.0); } QColor fill_color(colors.r, colors.g, colors.b); QColor border_color(colors.border_r, colors.border_g, colors.border_b); painter.setBrush(fill_color); painter.setPen(QPen(border_color, 1.2)); painter.drawEllipse(center, m_unit_radius, m_unit_radius); } void UnitLayer::draw_building_marker(QPainter &painter, float px, float py, const TeamColors::ColorSet &colors, bool is_selected) { const qreal half = static_cast(m_building_half_size); const QRectF rect(px - half, py - half, half * 2.0, half * 2.0); if (is_selected) { painter.setBrush(Qt::NoBrush); QPen glow_pen(QColor(TeamColors::SELECT_R, TeamColors::SELECT_G, TeamColors::SELECT_B, 200)); glow_pen.setWidthF(2.5); painter.setPen(glow_pen); painter.drawRect(rect.adjusted(-2.5, -2.5, 2.5, 2.5)); } QColor fill_color(colors.r, colors.g, colors.b); QColor border_color(colors.border_r, colors.border_g, colors.border_b); painter.setBrush(fill_color); painter.setPen(QPen(border_color, 1.5)); painter.drawRect(rect); const qreal inner = half * 0.4; painter.setBrush(border_color); painter.setPen(Qt::NoPen); painter.drawRect(QRectF(px - inner, py - inner, inner * 2.0, inner * 2.0)); } } // namespace Game::Map::Minimap