Add interactive production panel with unit/building tabs and district overview to city view
This commit is contained in:
+399
-21
@@ -587,7 +587,8 @@ void QSceneRenderer::drawUnitsOverlay(QPainter &painter, const QMatrix4x4 &vMatr
|
||||
const Player *pl = GameManager::instance().players().getPlayer(c.playerId);
|
||||
QColor col = pl ? pl->primaryColor : Qt::blue;
|
||||
|
||||
QRect bannerRect((int)screenP.x() - 55, (int)screenP.y() - 14, 110, 22);
|
||||
int bWidth = c.hasActiveProject() ? 150 : 110;
|
||||
QRect bannerRect((int)screenP.x() - bWidth / 2, (int)screenP.y() - 14, bWidth, 22);
|
||||
painter.setBrush(QColor(20, 24, 34, 235));
|
||||
painter.setPen(QPen(col, 2.0));
|
||||
painter.drawRoundedRect(bannerRect, 4, 4);
|
||||
@@ -595,6 +596,10 @@ void QSceneRenderer::drawUnitsOverlay(QPainter &painter, const QMatrix4x4 &vMatr
|
||||
painter.setFont(QFont("sans-serif", 8, QFont::Bold));
|
||||
painter.setPen(Qt::white);
|
||||
QString bannerText = QString("%1 (%2 Pop)").arg(c.name).arg(c.getTotalPop());
|
||||
if (c.hasActiveProject()) {
|
||||
int pct = (int)(c.currentProject.getProgress() * 100.0f);
|
||||
bannerText += QString(" | %1 %2%").arg(c.currentProject.name).arg(pct);
|
||||
}
|
||||
painter.drawText(bannerRect, Qt::AlignCenter, bannerText);
|
||||
|
||||
m_cityBannerHits.push_back({bannerRect, c.id});
|
||||
@@ -1256,7 +1261,7 @@ void QSceneRenderer::drawCityViewOverlay(QPainter &painter, const QMatrix4x4 &vM
|
||||
}
|
||||
|
||||
// 2. City Management Top Card
|
||||
int cardW = 560, cardH = 174;
|
||||
int cardW = 600, cardH = 174;
|
||||
QRect cardRect((width() - cardW) / 2, 14, cardW, cardH);
|
||||
|
||||
painter.setBrush(QColor(16, 22, 32, 245));
|
||||
@@ -1266,7 +1271,8 @@ void QSceneRenderer::drawCityViewOverlay(QPainter &painter, const QMatrix4x4 &vM
|
||||
// City Title & Close Button
|
||||
painter.setFont(QFont("sans-serif", 13, QFont::Bold));
|
||||
painter.setPen(QColor(245, 250, 255));
|
||||
painter.drawText(QRect(cardRect.left() + 16, cardRect.top() + 8, 300, 24), Qt::AlignLeft | Qt::AlignVCenter, city->name.toUpper() + " - STADSBEHEER");
|
||||
QString titleText = Localization::instance().get("ui.city.management_title", "%1 - CITY MANAGEMENT").arg(city->name.toUpper());
|
||||
painter.drawText(QRect(cardRect.left() + 16, cardRect.top() + 8, 380, 24), Qt::AlignLeft | Qt::AlignVCenter, titleText);
|
||||
|
||||
// Close button [X]
|
||||
m_closeCityViewBtnRect = QRect(cardRect.right() - 88, cardRect.top() + 8, 74, 24);
|
||||
@@ -1275,7 +1281,7 @@ void QSceneRenderer::drawCityViewOverlay(QPainter &painter, const QMatrix4x4 &vM
|
||||
painter.drawRoundedRect(m_closeCityViewBtnRect, 4, 4);
|
||||
painter.setFont(QFont("sans-serif", 8, QFont::Bold));
|
||||
painter.setPen(QColor(220, 235, 255));
|
||||
painter.drawText(m_closeCityViewBtnRect, Qt::AlignCenter, "[X] Sluiten");
|
||||
painter.drawText(m_closeCityViewBtnRect, Qt::AlignCenter, Localization::instance().get("ui.city.close_btn", "[X] Close"));
|
||||
|
||||
// Row 1: Population & Local Resources (Food & Labor are local to the city)
|
||||
int totalPop = city->getTotalPop();
|
||||
@@ -1284,7 +1290,7 @@ void QSceneRenderer::drawCityViewOverlay(QPainter &painter, const QMatrix4x4 &vM
|
||||
|
||||
painter.setFont(QFont("sans-serif", 8));
|
||||
painter.setPen(QColor(180, 205, 235));
|
||||
QString popInfo = QString("Lokaal: Inwoners: %L1 (%2 Pop: %3 aan het werk, %4 vrij) | Arbeid: %L5")
|
||||
QString popInfo = Localization::instance().get("ui.city.local_info", "Local: Population: %L1 (%2 Pop: %3 working, %4 free) | Labor: %L5")
|
||||
.arg(city->inhabitants).arg(totalPop).arg(assigned).arg(avail).arg(city->accumulatedLabor);
|
||||
painter.drawText(QRect(cardRect.left() + 16, cardRect.top() + 34, cardRect.width() - 32, 16), Qt::AlignLeft | Qt::AlignVCenter, popInfo);
|
||||
|
||||
@@ -1296,7 +1302,7 @@ void QSceneRenderer::drawCityViewOverlay(QPainter &painter, const QMatrix4x4 &vM
|
||||
|
||||
painter.setFont(QFont("sans-serif", 8, QFont::Bold));
|
||||
painter.setPen(QColor(220, 160, 255));
|
||||
QString natInfo = QString("Nationaal: Cultuur: %L1 | Kennis: %L2 | Goud: %L3 | Geloof: %L4")
|
||||
QString natInfo = Localization::instance().get("ui.city.national_info", "National: Culture: %L1 | Science: %L2 | Gold: %L3 | Faith: %L4")
|
||||
.arg(cult).arg(sci).arg(gld).arg(fth);
|
||||
painter.drawText(QRect(cardRect.left() + 16, cardRect.top() + 52, cardRect.width() - 32, 16), Qt::AlignLeft | Qt::AlignVCenter, natInfo);
|
||||
|
||||
@@ -1304,17 +1310,17 @@ void QSceneRenderer::drawCityViewOverlay(QPainter &painter, const QMatrix4x4 &vM
|
||||
painter.setPen(QPen(QColor(60, 85, 120, 150), 1.0));
|
||||
painter.drawLine(cardRect.left() + 16, cardRect.top() + 72, cardRect.right() - 16, cardRect.top() + 72);
|
||||
|
||||
// Row 3: Total Yields Summary Row (Base 500 + worked tiles)
|
||||
// Row 3: Total Yields Summary Row (Base 500 + worked tiles + buildings)
|
||||
CityYieldSummary summary = GameManager::instance().calculateCityYields(*city, m_point, m_numPoints05);
|
||||
|
||||
struct YieldItem { QString name; int val; QString icon; QColor col; };
|
||||
std::vector<YieldItem> yields = {
|
||||
{"Voedsel", summary.food, "images/resources/voedsel.png", QColor(100, 230, 110)},
|
||||
{"Arbeid", summary.labor, "images/resources/arbeid.png", QColor(240, 140, 50)},
|
||||
{"Kennis", summary.science, "images/resources/kennis.png", QColor(60, 190, 255)},
|
||||
{"Cultuur", summary.culture, "images/resources/cultuur.png", QColor(200, 110, 240)},
|
||||
{"Geloof", summary.faith, "images/resources/geloof.png", QColor(255, 230, 80)},
|
||||
{"Goud", summary.gold, "images/resources/goud.png", QColor(255, 210, 50)}
|
||||
{"Food", summary.food, "images/resources/voedsel.png", QColor(100, 230, 110)},
|
||||
{"Labor", summary.labor, "images/resources/arbeid.png", QColor(240, 140, 50)},
|
||||
{"Science", summary.science, "images/resources/kennis.png", QColor(60, 190, 255)},
|
||||
{"Culture", summary.culture, "images/resources/cultuur.png", QColor(200, 110, 240)},
|
||||
{"Faith", summary.faith, "images/resources/geloof.png", QColor(255, 230, 80)},
|
||||
{"Gold", summary.gold, "images/resources/goud.png", QColor(255, 210, 50)}
|
||||
};
|
||||
|
||||
int colW = (cardRect.width() - 32) / 6;
|
||||
@@ -1338,17 +1344,358 @@ void QSceneRenderer::drawCityViewOverlay(QPainter &painter, const QMatrix4x4 &vM
|
||||
painter.drawText(QRect(yRect.left() + 6, yRect.top() + 22, yRect.width() - 12, 16), Qt::AlignLeft | Qt::AlignVCenter, QString("+%1/tick").arg(yields[i].val));
|
||||
}
|
||||
|
||||
// Help instruction at bottom
|
||||
// Help instruction at bottom of top card
|
||||
painter.setFont(QFont("sans-serif", 7, QFont::StyleItalic));
|
||||
painter.setPen(QColor(140, 170, 200));
|
||||
painter.drawText(QRect(cardRect.left() + 16, cardRect.bottom() - 18, cardRect.width() - 32, 16), Qt::AlignCenter,
|
||||
"Klik op een tegel om 1 Pop toe te wijzen | Klik op een vrije tegel om deze te kopen met Cultuur.");
|
||||
Localization::instance().get("ui.city.help_text", "Click a tile to assign 1 Pop | Click an unowned tile to buy with Culture."));
|
||||
|
||||
// 3. City Production & Districts Bottom Panel
|
||||
int panelW = std::min(980, width() - 40);
|
||||
int panelH = 195;
|
||||
QRect prodPanelRect((width() - panelW) / 2, height() - panelH - 14, panelW, panelH);
|
||||
|
||||
painter.setBrush(QColor(16, 22, 32, 248));
|
||||
painter.setPen(QPen(primaryCol, 1.8));
|
||||
painter.drawRoundedRect(prodPanelRect, 10, 10);
|
||||
|
||||
// Left Column: Active Production & District (width 340)
|
||||
int leftColW = 340;
|
||||
QRect leftColRect(prodPanelRect.left() + 14, prodPanelRect.top() + 10, leftColW, panelH - 20);
|
||||
|
||||
// Header: Current Production
|
||||
painter.setFont(QFont("sans-serif", 9, QFont::Bold));
|
||||
painter.setPen(QColor(230, 240, 255));
|
||||
painter.drawText(QRect(leftColRect.left(), leftColRect.top(), leftColRect.width(), 18),
|
||||
Qt::AlignLeft | Qt::AlignVCenter,
|
||||
Localization::instance().get("ui.city.current_production", "CURRENT PRODUCTION"));
|
||||
|
||||
if (city->hasActiveProject()) {
|
||||
const CityProject &proj = city->currentProject;
|
||||
float progress = proj.getProgress();
|
||||
int pct = (int)(progress * 100.0f);
|
||||
int remainingLabor = proj.getRemainingLabor();
|
||||
int laborRate = std::max(1, summary.labor);
|
||||
int estTicks = (int)std::ceil((float)remainingLabor / (float)laborRate);
|
||||
|
||||
// Project Icon & Name
|
||||
QString projIconPath = "images/improvements/granary.png";
|
||||
if (proj.type == CityProjectType::Unit) {
|
||||
const UnitConfig *uCfg = GameManager::instance().unitConfigs().getConfig(proj.id);
|
||||
if (uCfg && !uCfg->iconPath.isEmpty()) projIconPath = uCfg->iconPath;
|
||||
} else if (proj.type == CityProjectType::Building) {
|
||||
const BuildingConfig *bCfg = GameManager::instance().buildingConfigs().getBuilding(proj.id);
|
||||
if (bCfg && !bCfg->iconPath.isEmpty()) projIconPath = bCfg->iconPath;
|
||||
}
|
||||
QImage pIcon = getTintedIcon(projIconPath, QColor(255, 215, 60));
|
||||
painter.drawImage(QRect(leftColRect.left(), leftColRect.top() + 24, 28, 28), pIcon);
|
||||
|
||||
painter.setFont(QFont("sans-serif", 10, QFont::Bold));
|
||||
painter.setPen(QColor(255, 235, 120));
|
||||
painter.drawText(QRect(leftColRect.left() + 34, leftColRect.top() + 22, 220, 18),
|
||||
Qt::AlignLeft | Qt::AlignVCenter, proj.name);
|
||||
|
||||
painter.setFont(QFont("sans-serif", 7));
|
||||
painter.setPen(QColor(170, 195, 220));
|
||||
QString typeDesc = (proj.type == CityProjectType::Unit) ? "Unit" : QString("Building (%1)").arg(proj.district);
|
||||
painter.drawText(QRect(leftColRect.left() + 34, leftColRect.top() + 38, 220, 14),
|
||||
Qt::AlignLeft | Qt::AlignVCenter, typeDesc);
|
||||
|
||||
// Cancel button
|
||||
m_cancelProjectBtnRect = QRect(leftColRect.right() - 65, leftColRect.top() + 24, 65, 22);
|
||||
painter.setBrush(QColor(50, 25, 30, 220));
|
||||
painter.setPen(QPen(QColor(220, 90, 90), 1.0));
|
||||
painter.drawRoundedRect(m_cancelProjectBtnRect, 4, 4);
|
||||
painter.setFont(QFont("sans-serif", 7, QFont::Bold));
|
||||
painter.setPen(QColor(255, 150, 150));
|
||||
painter.drawText(m_cancelProjectBtnRect, Qt::AlignCenter,
|
||||
Localization::instance().get("ui.city.cancel_btn", "Cancel"));
|
||||
|
||||
// Progress Bar
|
||||
QRect barBg(leftColRect.left(), leftColRect.top() + 56, leftColRect.width(), 16);
|
||||
painter.setBrush(QColor(25, 35, 48));
|
||||
painter.setPen(QPen(QColor(60, 85, 120), 1.0));
|
||||
painter.drawRoundedRect(barBg, 3, 3);
|
||||
|
||||
QRect barFg(leftColRect.left(), leftColRect.top() + 56, (int)(leftColRect.width() * progress), 16);
|
||||
painter.setBrush(QColor(240, 145, 40));
|
||||
painter.setPen(Qt::NoPen);
|
||||
painter.drawRoundedRect(barFg, 3, 3);
|
||||
|
||||
painter.setFont(QFont("sans-serif", 7, QFont::Bold));
|
||||
painter.setPen(Qt::white);
|
||||
QString progText = QString("%1% (%L2 / %L3 Labor)").arg(pct).arg(proj.currentLabor).arg(proj.laborCost);
|
||||
painter.drawText(barBg, Qt::AlignCenter, progText);
|
||||
|
||||
// Subtitle: Estimated ticks remaining
|
||||
painter.setFont(QFont("sans-serif", 7));
|
||||
painter.setPen(QColor(160, 185, 215));
|
||||
painter.drawText(QRect(leftColRect.left(), leftColRect.top() + 74, leftColRect.width(), 14),
|
||||
Qt::AlignLeft | Qt::AlignVCenter,
|
||||
QString("~%1 %2 remaining (+%3 Labor/tick)")
|
||||
.arg(estTicks).arg(estTicks == 1 ? "tick" : "ticks").arg(laborRate));
|
||||
} else {
|
||||
// No project active
|
||||
painter.setFont(QFont("sans-serif", 9, QFont::StyleItalic));
|
||||
painter.setPen(QColor(180, 195, 210));
|
||||
painter.drawText(QRect(leftColRect.left(), leftColRect.top() + 28, leftColRect.width(), 20),
|
||||
Qt::AlignLeft | Qt::AlignVCenter,
|
||||
Localization::instance().get("ui.city.no_project", "No active project"));
|
||||
|
||||
painter.setFont(QFont("sans-serif", 7));
|
||||
painter.setPen(QColor(140, 160, 180));
|
||||
painter.drawText(QRect(leftColRect.left(), leftColRect.top() + 50, leftColRect.width(), 30),
|
||||
Qt::AlignLeft | Qt::TextWordWrap,
|
||||
Localization::instance().get("ui.city.select_prompt", "Select a unit or building to construct"));
|
||||
}
|
||||
|
||||
// Separator between project and districts
|
||||
painter.setPen(QPen(QColor(60, 85, 120, 150), 1.0));
|
||||
painter.drawLine(leftColRect.left(), leftColRect.top() + 94, leftColRect.right(), leftColRect.top() + 94);
|
||||
|
||||
// District Section: Centrum / City Center
|
||||
painter.setFont(QFont("sans-serif", 8, QFont::Bold));
|
||||
painter.setPen(QColor(220, 200, 140));
|
||||
painter.drawText(QRect(leftColRect.left(), leftColRect.top() + 100, leftColRect.width(), 16),
|
||||
Qt::AlignLeft | Qt::AlignVCenter,
|
||||
Localization::instance().get("ui.city.districts_header", "DISTRICT: CITY CENTER"));
|
||||
|
||||
// Completed buildings inside this district
|
||||
int bCount = 0;
|
||||
int bOffsetY = leftColRect.top() + 120;
|
||||
for (const QString &bId : city->completedBuildings) {
|
||||
const BuildingConfig *bCfg = GameManager::instance().buildingConfigs().getBuilding(bId);
|
||||
if (!bCfg) continue;
|
||||
|
||||
QRect bBadge(leftColRect.left() + bCount * 168, bOffsetY, 162, 46);
|
||||
painter.setBrush(QColor(25, 38, 30, 220));
|
||||
painter.setPen(QPen(QColor(80, 220, 120), 1.2));
|
||||
painter.drawRoundedRect(bBadge, 4, 4);
|
||||
|
||||
QImage bIcon = getTintedIcon(bCfg->iconPath.isEmpty() ? "images/improvements/granary.png" : bCfg->iconPath, QColor(80, 240, 120));
|
||||
painter.drawImage(QRect(bBadge.left() + 6, bBadge.top() + 6, 20, 20), bIcon);
|
||||
|
||||
painter.setFont(QFont("sans-serif", 8, QFont::Bold));
|
||||
painter.setPen(QColor(210, 255, 220));
|
||||
painter.drawText(QRect(bBadge.left() + 30, bBadge.top() + 4, bBadge.width() - 34, 16),
|
||||
Qt::AlignLeft | Qt::AlignVCenter, bCfg->name);
|
||||
|
||||
painter.setFont(QFont("sans-serif", 7));
|
||||
painter.setPen(QColor(160, 230, 180));
|
||||
painter.drawText(QRect(bBadge.left() + 6, bBadge.top() + 24, bBadge.width() - 10, 16),
|
||||
Qt::AlignLeft | Qt::AlignVCenter, bCfg->description);
|
||||
bCount++;
|
||||
if (bCount >= 2) break;
|
||||
}
|
||||
|
||||
if (city->completedBuildings.empty()) {
|
||||
painter.setFont(QFont("sans-serif", 7, QFont::StyleItalic));
|
||||
painter.setPen(QColor(140, 160, 180));
|
||||
painter.drawText(QRect(leftColRect.left(), bOffsetY + 8, leftColRect.width(), 16),
|
||||
Qt::AlignLeft | Qt::AlignVCenter,
|
||||
Localization::instance().get("ui.city.no_buildings", "No extensions built yet"));
|
||||
}
|
||||
|
||||
// Vertical divider line between left and right columns
|
||||
int divX = leftColRect.right() + 14;
|
||||
painter.setPen(QPen(QColor(60, 85, 120, 150), 1.0));
|
||||
painter.drawLine(divX, prodPanelRect.top() + 10, divX, prodPanelRect.bottom() - 10);
|
||||
|
||||
// Right Column: Project Selection (Tabs + Items)
|
||||
int rightColX = divX + 14;
|
||||
int rightColW = prodPanelRect.right() - rightColX - 14;
|
||||
|
||||
// Header & Tabs
|
||||
painter.setFont(QFont("sans-serif", 9, QFont::Bold));
|
||||
painter.setPen(QColor(230, 240, 255));
|
||||
painter.drawText(QRect(rightColX, prodPanelRect.top() + 10, 160, 20),
|
||||
Qt::AlignLeft | Qt::AlignVCenter,
|
||||
Localization::instance().get("ui.city.choose_project", "CHOOSE CITY PROJECT"));
|
||||
|
||||
// Tabs: [Buildings & Extensions] and [Units]
|
||||
int tabW = 155, tabH = 22;
|
||||
m_tabBuildingsRect = QRect(rightColX + 170, prodPanelRect.top() + 9, tabW, tabH);
|
||||
m_tabUnitsRect = QRect(m_tabBuildingsRect.right() + 8, prodPanelRect.top() + 9, 90, tabH);
|
||||
|
||||
// Draw Tab Buildings
|
||||
bool isBTab = (m_cityProjectTab == 0);
|
||||
painter.setBrush(isBTab ? QColor(45, 75, 120, 240) : QColor(25, 35, 50, 180));
|
||||
painter.setPen(QPen(isBTab ? QColor(100, 190, 255) : QColor(60, 85, 120), isBTab ? 1.5 : 1.0));
|
||||
painter.drawRoundedRect(m_tabBuildingsRect, 4, 4);
|
||||
painter.setFont(QFont("sans-serif", 8, isBTab ? QFont::Bold : QFont::Normal));
|
||||
painter.setPen(isBTab ? Qt::white : QColor(160, 185, 215));
|
||||
painter.drawText(m_tabBuildingsRect, Qt::AlignCenter,
|
||||
Localization::instance().get("ui.city.tab_buildings", "Buildings & Extensions"));
|
||||
|
||||
// Draw Tab Units
|
||||
bool isUTab = (m_cityProjectTab == 1);
|
||||
painter.setBrush(isUTab ? QColor(45, 75, 120, 240) : QColor(25, 35, 50, 180));
|
||||
painter.setPen(QPen(isUTab ? QColor(100, 190, 255) : QColor(60, 85, 120), isUTab ? 1.5 : 1.0));
|
||||
painter.drawRoundedRect(m_tabUnitsRect, 4, 4);
|
||||
painter.setFont(QFont("sans-serif", 8, isUTab ? QFont::Bold : QFont::Normal));
|
||||
painter.setPen(isUTab ? Qt::white : QColor(160, 185, 215));
|
||||
painter.drawText(m_tabUnitsRect, Qt::AlignCenter,
|
||||
Localization::instance().get("ui.city.tab_units", "Units"));
|
||||
|
||||
// Render Items under active tab
|
||||
int listY = prodPanelRect.top() + 38;
|
||||
int itemH = 65;
|
||||
|
||||
if (m_cityProjectTab == 0) {
|
||||
// Buildings tab
|
||||
const auto &buildings = GameManager::instance().buildingConfigs().getAllBuildings();
|
||||
int idx = 0;
|
||||
int colItemW = (rightColW - 10) / 2;
|
||||
|
||||
for (auto it = buildings.begin(); it != buildings.end(); ++it) {
|
||||
const BuildingConfig &bCfg = it.value();
|
||||
int ix = rightColX + (idx % 2) * (colItemW + 10);
|
||||
int iy = listY + (idx / 2) * (itemH + 6);
|
||||
QRect itemRect(ix, iy, colItemW, itemH);
|
||||
|
||||
bool alreadyBuilt = city->hasBuilding(bCfg.id);
|
||||
bool isActiveProj = (city->hasActiveProject() && city->currentProject.type == CityProjectType::Building && city->currentProject.id == bCfg.id);
|
||||
|
||||
painter.setBrush(isActiveProj ? QColor(35, 50, 75, 230) : (alreadyBuilt ? QColor(20, 25, 32, 190) : QColor(24, 32, 46, 220)));
|
||||
painter.setPen(QPen(isActiveProj ? QColor(255, 220, 50) : (alreadyBuilt ? QColor(60, 75, 95) : QColor(70, 100, 140)), isActiveProj ? 1.8 : 1.0));
|
||||
painter.drawRoundedRect(itemRect, 6, 6);
|
||||
|
||||
// Icon
|
||||
QImage bIcon = getTintedIcon(bCfg.iconPath.isEmpty() ? "images/improvements/granary.png" : bCfg.iconPath,
|
||||
alreadyBuilt ? QColor(120, 140, 160) : QColor(255, 215, 60));
|
||||
painter.drawImage(QRect(itemRect.left() + 8, itemRect.top() + 8, 28, 28), bIcon);
|
||||
|
||||
// Building Name
|
||||
painter.setFont(QFont("sans-serif", 8, QFont::Bold));
|
||||
painter.setPen(alreadyBuilt ? QColor(150, 165, 180) : QColor(245, 250, 255));
|
||||
painter.drawText(QRect(itemRect.left() + 42, itemRect.top() + 6, itemRect.width() - 110, 16),
|
||||
Qt::AlignLeft | Qt::AlignVCenter, bCfg.name);
|
||||
|
||||
// District & Cost
|
||||
int estTicks = (int)std::ceil((float)bCfg.laborCost / (float)std::max(1, summary.labor));
|
||||
painter.setFont(QFont("sans-serif", 7));
|
||||
painter.setPen(QColor(240, 160, 50));
|
||||
QString costStr = QString("%L1 Labor (%2 %3)").arg(bCfg.laborCost).arg(estTicks).arg(estTicks == 1 ? "tick" : "ticks");
|
||||
painter.drawText(QRect(itemRect.left() + 42, itemRect.top() + 22, itemRect.width() - 110, 14),
|
||||
Qt::AlignLeft | Qt::AlignVCenter, costStr);
|
||||
|
||||
// Description / Effect
|
||||
painter.setFont(QFont("sans-serif", 7));
|
||||
painter.setPen(alreadyBuilt ? QColor(120, 180, 140) : QColor(100, 240, 130));
|
||||
painter.drawText(QRect(itemRect.left() + 42, itemRect.top() + 38, itemRect.width() - 50, 16),
|
||||
Qt::AlignLeft | Qt::AlignVCenter, bCfg.description);
|
||||
|
||||
// Action Button / Status badge on right side
|
||||
QRect btnRect(itemRect.right() - 66, itemRect.top() + 10, 58, 24);
|
||||
if (alreadyBuilt) {
|
||||
painter.setBrush(QColor(30, 40, 35, 180));
|
||||
painter.setPen(QPen(QColor(70, 120, 85), 1.0));
|
||||
painter.drawRoundedRect(btnRect, 4, 4);
|
||||
painter.setFont(QFont("sans-serif", 7, QFont::Bold));
|
||||
painter.setPen(QColor(120, 180, 130));
|
||||
painter.drawText(btnRect, Qt::AlignCenter,
|
||||
Localization::instance().get("ui.city.status_built", "BUILT"));
|
||||
} else if (isActiveProj) {
|
||||
painter.setBrush(QColor(60, 50, 20, 220));
|
||||
painter.setPen(QPen(QColor(255, 215, 50), 1.2));
|
||||
painter.drawRoundedRect(btnRect, 4, 4);
|
||||
painter.setFont(QFont("sans-serif", 7, QFont::Bold));
|
||||
painter.setPen(QColor(255, 230, 80));
|
||||
painter.drawText(btnRect, Qt::AlignCenter,
|
||||
Localization::instance().get("ui.city.status_in_progress", "ACTIVE"));
|
||||
} else {
|
||||
painter.setBrush(QColor(30, 60, 100, 240));
|
||||
painter.setPen(QPen(QColor(80, 160, 255), 1.2));
|
||||
painter.drawRoundedRect(btnRect, 4, 4);
|
||||
painter.setFont(QFont("sans-serif", 7, QFont::Bold));
|
||||
painter.setPen(Qt::white);
|
||||
painter.drawText(btnRect, Qt::AlignCenter,
|
||||
Localization::instance().get("ui.city.btn_build", "Build"));
|
||||
|
||||
m_cityProjectHits.push_back({btnRect, CityProjectType::Building, bCfg.id});
|
||||
}
|
||||
|
||||
idx++;
|
||||
}
|
||||
} else {
|
||||
// Units tab
|
||||
const auto &units = GameManager::instance().unitConfigs().getAllConfigs();
|
||||
int idx = 0;
|
||||
int colItemW = (rightColW - 10) / 2;
|
||||
|
||||
for (auto it = units.begin(); it != units.end(); ++it) {
|
||||
const UnitConfig &uCfg = it.value();
|
||||
int ix = rightColX + (idx % 2) * (colItemW + 10);
|
||||
int iy = listY + (idx / 2) * (itemH + 6);
|
||||
QRect itemRect(ix, iy, colItemW, itemH);
|
||||
|
||||
bool isActiveProj = (city->hasActiveProject() && city->currentProject.type == CityProjectType::Unit && city->currentProject.id == uCfg.id);
|
||||
|
||||
painter.setBrush(isActiveProj ? QColor(35, 50, 75, 230) : QColor(24, 32, 46, 220));
|
||||
painter.setPen(QPen(isActiveProj ? QColor(255, 220, 50) : QColor(70, 100, 140), isActiveProj ? 1.8 : 1.0));
|
||||
painter.drawRoundedRect(itemRect, 6, 6);
|
||||
|
||||
// Icon
|
||||
QImage uIcon = getTintedIcon(uCfg.iconPath, primaryCol);
|
||||
painter.drawImage(QRect(itemRect.left() + 8, itemRect.top() + 8, 28, 28), uIcon);
|
||||
|
||||
// Unit Name
|
||||
painter.setFont(QFont("sans-serif", 8, QFont::Bold));
|
||||
painter.setPen(QColor(245, 250, 255));
|
||||
painter.drawText(QRect(itemRect.left() + 42, itemRect.top() + 6, itemRect.width() - 110, 16),
|
||||
Qt::AlignLeft | Qt::AlignVCenter, uCfg.name);
|
||||
|
||||
// Cost & Estimated Ticks
|
||||
int estTicks = (int)std::ceil((float)uCfg.laborCost / (float)std::max(1, summary.labor));
|
||||
painter.setFont(QFont("sans-serif", 7));
|
||||
painter.setPen(QColor(240, 160, 50));
|
||||
QString costStr = QString("%L1 Labor (%2 %3)").arg(uCfg.laborCost).arg(estTicks).arg(estTicks == 1 ? "tick" : "ticks");
|
||||
painter.drawText(QRect(itemRect.left() + 42, itemRect.top() + 22, itemRect.width() - 110, 14),
|
||||
Qt::AlignLeft | Qt::AlignVCenter, costStr);
|
||||
|
||||
// Stats info
|
||||
painter.setFont(QFont("sans-serif", 7));
|
||||
painter.setPen(QColor(160, 185, 215));
|
||||
QString infoStr = unitCategoryToString(uCfg.category);
|
||||
if (uCfg.isMilitary()) {
|
||||
infoStr += QString(" | HP: %1 | Atk: %2").arg(uCfg.health).arg(uCfg.attackDamage);
|
||||
}
|
||||
painter.drawText(QRect(itemRect.left() + 42, itemRect.top() + 38, itemRect.width() - 50, 16),
|
||||
Qt::AlignLeft | Qt::AlignVCenter, infoStr);
|
||||
|
||||
// Action Button / Status badge on right side
|
||||
QRect btnRect(itemRect.right() - 66, itemRect.top() + 10, 58, 24);
|
||||
if (isActiveProj) {
|
||||
painter.setBrush(QColor(60, 50, 20, 220));
|
||||
painter.setPen(QPen(QColor(255, 215, 50), 1.2));
|
||||
painter.drawRoundedRect(btnRect, 4, 4);
|
||||
painter.setFont(QFont("sans-serif", 7, QFont::Bold));
|
||||
painter.setPen(QColor(255, 230, 80));
|
||||
painter.drawText(btnRect, Qt::AlignCenter,
|
||||
Localization::instance().get("ui.city.status_in_progress", "ACTIVE"));
|
||||
} else {
|
||||
painter.setBrush(QColor(30, 60, 100, 240));
|
||||
painter.setPen(QPen(QColor(80, 160, 255), 1.2));
|
||||
painter.drawRoundedRect(btnRect, 4, 4);
|
||||
painter.setFont(QFont("sans-serif", 7, QFont::Bold));
|
||||
painter.setPen(Qt::white);
|
||||
painter.drawText(btnRect, Qt::AlignCenter,
|
||||
Localization::instance().get("ui.city.btn_train", "Train"));
|
||||
|
||||
m_cityProjectHits.push_back({btnRect, CityProjectType::Unit, uCfg.id});
|
||||
}
|
||||
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QSceneRenderer::mousePressEvent(QMouseEvent *event)
|
||||
{
|
||||
// 0. If in City View: handle close button and slot clicks
|
||||
// 0. If in City View: handle close button, project tabs/hits, cancel, and slot clicks
|
||||
if (GameManager::instance().isInCityView()) {
|
||||
City *city = GameManager::instance().getActiveCityView();
|
||||
|
||||
if (m_closeCityViewBtnRect.contains(event->pos())) {
|
||||
cameraPosition = m_savedCamPos;
|
||||
m_zoom = m_savedZoom;
|
||||
@@ -1358,21 +1705,53 @@ void QSceneRenderer::mousePressEvent(QMouseEvent *event)
|
||||
return;
|
||||
}
|
||||
|
||||
// Tab switches
|
||||
if (m_tabBuildingsRect.contains(event->pos())) {
|
||||
m_cityProjectTab = 0;
|
||||
update();
|
||||
return;
|
||||
}
|
||||
if (m_tabUnitsRect.contains(event->pos())) {
|
||||
m_cityProjectTab = 1;
|
||||
update();
|
||||
return;
|
||||
}
|
||||
|
||||
// Cancel project
|
||||
if (city && m_cancelProjectBtnRect.contains(event->pos())) {
|
||||
GameManager::instance().cancelCityProject(city->id);
|
||||
update();
|
||||
return;
|
||||
}
|
||||
|
||||
// Project selection clicks
|
||||
if (city) {
|
||||
for (const auto &pHit : m_cityProjectHits) {
|
||||
if (pHit.rect.contains(event->pos())) {
|
||||
GameManager::instance().setCityProject(city->id, pHit.type, pHit.id);
|
||||
update();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto &slot : m_citySlotHits) {
|
||||
if (slot.rect.contains(event->pos())) {
|
||||
City *city = GameManager::instance().getActiveCityView();
|
||||
if (city) {
|
||||
QVector2D w = Pathfinder::hexToWorld(slot.tx, slot.ty);
|
||||
float gz = Unit::getTerrainHeight(w.x(), w.y(), m_point, m_numPoints05);
|
||||
if (city->isTileWorked(slot.tx, slot.ty)) {
|
||||
city->unassignWorker(slot.tx, slot.ty);
|
||||
GameManager::instance().addFloatingText("Pop vrijgemaakt", QVector3D(w.x(), w.y(), gz + 0.8f), QColor(255, 220, 80));
|
||||
QString msg = Localization::instance().get("ui.city.worker_freed", "Pop worker freed");
|
||||
GameManager::instance().addFloatingText(msg, QVector3D(w.x(), w.y(), gz + 0.8f), QColor(255, 220, 80));
|
||||
} else {
|
||||
if (city->getAvailablePop() > 0) {
|
||||
city->assignWorker(slot.tx, slot.ty, slot.defaultRes);
|
||||
GameManager::instance().addFloatingText("+1 Pop aan het werk", QVector3D(w.x(), w.y(), gz + 0.8f), QColor(80, 255, 120));
|
||||
QString msg = Localization::instance().get("ui.city.worker_assigned", "+1 Pop working");
|
||||
GameManager::instance().addFloatingText(msg, QVector3D(w.x(), w.y(), gz + 0.8f), QColor(80, 255, 120));
|
||||
} else {
|
||||
GameManager::instance().addFloatingText("Geen vrije Pop!", QVector3D(w.x(), w.y(), gz + 0.8f), QColor(255, 80, 80));
|
||||
QString msg = Localization::instance().get("ui.city.no_free_pop", "No free Pop!");
|
||||
GameManager::instance().addFloatingText(msg, QVector3D(w.x(), w.y(), gz + 0.8f), QColor(255, 80, 80));
|
||||
}
|
||||
}
|
||||
update();
|
||||
@@ -1384,7 +1763,6 @@ void QSceneRenderer::mousePressEvent(QMouseEvent *event)
|
||||
// 2. Buy tile clicks
|
||||
for (const auto &buyHit : m_cityBuyTileHits) {
|
||||
if (buyHit.rect.contains(event->pos())) {
|
||||
City *city = GameManager::instance().getActiveCityView();
|
||||
if (city) {
|
||||
GameManager::instance().buyTileForCity(city->id, buyHit.tx, buyHit.ty);
|
||||
update();
|
||||
|
||||
Reference in New Issue
Block a user