add live ship stats panel

This commit is contained in:
2026-06-07 21:07:19 +02:00
parent 37a70ea321
commit f097e9a25f
20 changed files with 723 additions and 45 deletions

View File

@@ -20,6 +20,8 @@
#include "BeltSystem.h"
#include "Building.h"
#include "BuildingSystem.h"
#include "EntityHitTest.h"
#include "EntitySelectedEvent.h"
#include "EventManager.h"
#include "FacingComponent.h"
#include "FactionComponent.h"
@@ -338,6 +340,13 @@ QPoint GameWorldView::widgetToTile(QPoint widgetPt) const
return QPoint(static_cast<int>(std::floor(wx)), static_cast<int>(std::floor(wy)));
}
QVector2D GameWorldView::widgetToWorld(QPoint widgetPt) const
{
const float wx = static_cast<float>(widgetPt.x()) / tilePx() + m_scrollXTiles;
const float wy = static_cast<float>(widgetPt.y()) / tilePx();
return QVector2D(wx, wy);
}
QRectF GameWorldView::tileRect(QPoint tile) const
{
const QPointF tl = tileToWidget(tile);
@@ -834,7 +843,7 @@ void GameWorldView::drawScrap(QPainter& painter)
void GameWorldView::drawStations(QPainter& painter)
{
m_sim->admin().forEach<StationBodyComponent, FactionComponent, HealthComponent>(
[&](entt::entity /*e*/, const StationBodyComponent& sb, const FactionComponent& f,
[&](entt::entity e, const StationBodyComponent& sb, const FactionComponent& f,
const HealthComponent& h)
{
const BuildingType visType = f.isEnemy
@@ -860,6 +869,13 @@ void GameWorldView::drawStations(QPainter& painter)
painter.setBrush(Qt::NoBrush);
painter.drawRect(bboxRect);
if (m_selectedEntity.has_value() && *m_selectedEntity == e)
{
painter.setPen(QPen(m_visuals->overlays.selectedOutline, 2));
painter.setBrush(Qt::NoBrush);
painter.drawRect(bboxRect.adjusted(-2, -2, 2, 2));
}
// HP bar below footprint.
if (h.maxHp > 0.0f)
{
@@ -879,7 +895,7 @@ void GameWorldView::drawShips(QPainter& painter)
{
m_sim->admin().forEach<ShipIdentityComponent, PositionComponent, FacingComponent,
FactionComponent, HealthComponent>(
[&](entt::entity /*e*/, const ShipIdentityComponent& si,
[&](entt::entity e, const ShipIdentityComponent& si,
const PositionComponent& pos, const FacingComponent& facing,
const FactionComponent& fac, const HealthComponent& h)
{
@@ -906,6 +922,14 @@ void GameWorldView::drawShips(QPainter& painter)
painter.setBrush(it->second.fill);
painter.drawPolygon(tri);
if (m_selectedEntity.has_value() && *m_selectedEntity == e)
{
painter.setPen(QPen(m_visuals->overlays.selectedOutline, 2));
painter.setBrush(Qt::NoBrush);
const qreal r = static_cast<qreal>(fwd) + 2.0;
painter.drawEllipse(center, r, r);
}
if (h.maxHp > 0.0f)
{
const float fraction = std::max(0.0f, h.hp / h.maxHp);
@@ -1271,41 +1295,62 @@ void GameWorldView::mousePressEvent(QMouseEvent* event)
}
else
{
BuildingId id = buildingAtTile(tile);
if (id == kInvalidBuildingId)
const QVector2D worldPos = widgetToWorld(event->pos());
const entt::entity hitEntity = entityAtWorldPos(m_sim->admin(), worldPos);
if (hitEntity != entt::null)
{
id = siteAtTile(tile);
}
if (id != kInvalidBuildingId)
{
if (event->modifiers() & Qt::ControlModifier)
{
bool found = false;
std::vector<BuildingId> newSel;
for (BuildingId sel : m_selectedBuildingIds)
{
if (sel == id) { found = true; }
else { newSel.push_back(sel); }
}
if (!found) { newSel.push_back(id); }
m_selectedBuildingIds = newSel;
}
else
{
m_selectedBuildingIds = { id };
}
m_selectedBuildingIds.clear();
emit selectionChanged(m_selectedBuildingIds);
m_selectedEntity = hitEntity;
EventManager::getInstance()->sendEventImmediately(
std::make_shared<EntitySelectedEvent>(hitEntity));
}
else
{
if (!(event->modifiers() & Qt::ControlModifier))
if (m_selectedEntity.has_value())
{
m_selectedBuildingIds.clear();
m_selectedEntity = std::nullopt;
EventManager::getInstance()->sendEventImmediately(
std::make_shared<EntitySelectedEvent>(std::nullopt));
}
BuildingId id = buildingAtTile(tile);
if (id == kInvalidBuildingId)
{
id = siteAtTile(tile);
}
if (id != kInvalidBuildingId)
{
if (event->modifiers() & Qt::ControlModifier)
{
bool found = false;
std::vector<BuildingId> newSel;
for (BuildingId sel : m_selectedBuildingIds)
{
if (sel == id) { found = true; }
else { newSel.push_back(sel); }
}
if (!found) { newSel.push_back(id); }
m_selectedBuildingIds = newSel;
}
else
{
m_selectedBuildingIds = { id };
}
emit selectionChanged(m_selectedBuildingIds);
}
m_boxSelecting = true;
m_boxStartTile = tile;
m_boxCurrentTile = tile;
else
{
if (!(event->modifiers() & Qt::ControlModifier))
{
m_selectedBuildingIds.clear();
emit selectionChanged(m_selectedBuildingIds);
}
m_boxSelecting = true;
m_boxStartTile = tile;
m_boxCurrentTile = tile;
}
}
}
}