Rename ship/station scrap drop entities to "debris"

This commit is contained in:
2026-07-23 20:51:05 +02:00
parent 11daa61714
commit 8b71fe1a03
48 changed files with 468 additions and 443 deletions

View File

@@ -52,15 +52,15 @@
#include "PositionComponent.h"
#include "RepairBehavior.h"
#include "SalvageScrapBehavior.h"
#include "ScrapSelectionChangedEvent.h"
#include "ScrapSystem.h"
#include "DebrisSelectionChangedEvent.h"
#include "DebrisSystem.h"
#include "SelectionChangedEvent.h"
#include "SensorRangeComponent.h"
#include "ShipIdentityComponent.h"
#include "ShipSystem.h"
#include "Simulation.h"
#include "StationBodyComponent.h"
#include "ScrapDataComponent.h"
#include "DebrisComponent.h"
#include "SurfaceMask.h"
#include "Tick.h"
#include "TunnelCompletion.h"
@@ -350,9 +350,9 @@ void GameWorldView::onFrame()
m_activeBeams = std::move(live);
}
// Drop selected scrap piles that were collected or despawned this frame, so the
// panel stops counting them and the selection empties out (REQ-UI-SCRAP-CLICK-SELECT).
pruneDespawnedScrap();
// Drop selected debris that were collected or despawned this frame, so the
// panel stops counting them and the selection empties out (REQ-UI-DEBRIS-CLICK-SELECT).
pruneDespawnedDebris();
pruneDespawnedActors();
// Expire copy/paste flashes. Lifetime is wall-clock (the frame delta), so the
@@ -504,7 +504,7 @@ void GameWorldView::paintGL()
drawCopyConfigFeedback(painter);
drawStations(painter);
drawBeltItems(painter);
drawScrap(painter);
drawDebris(painter);
if (m_debugDraw)
{
drawDebugSensorRanges(painter);
@@ -779,33 +779,33 @@ std::optional<QVector2D> GameWorldView::entityPosition(entt::entity entity) cons
return m_sim->getAdmin().get<PositionComponent>(entity).value;
}
void GameWorldView::clearScrapSelection()
void GameWorldView::clearDebrisSelection()
{
if (m_selectedScrap.empty()) { return; }
m_selectedScrap.clear();
if (m_selectedDebris.empty()) { return; }
m_selectedDebris.clear();
EventManager::getInstance()->sendEventImmediately(
std::make_shared<ScrapSelectionChangedEvent>(m_selectedScrap));
std::make_shared<DebrisSelectionChangedEvent>(m_selectedDebris));
}
void GameWorldView::pruneDespawnedScrap()
void GameWorldView::pruneDespawnedDebris()
{
if (m_selectedScrap.empty()) { return; }
if (m_selectedDebris.empty()) { return; }
std::vector<entt::entity> live;
for (const ScrapInfo& info : m_sim->getScraps().getAllScrapInfo())
for (const DebrisInfo& info : m_sim->getDebrisSystem().getAllDebrisInfo())
{
if (std::find(m_selectedScrap.begin(), m_selectedScrap.end(), info.entity)
!= m_selectedScrap.end())
if (std::find(m_selectedDebris.begin(), m_selectedDebris.end(), info.entity)
!= m_selectedDebris.end())
{
live.push_back(info.entity);
}
}
if (live.size() != m_selectedScrap.size())
if (live.size() != m_selectedDebris.size())
{
m_selectedScrap = std::move(live);
m_selectedDebris = std::move(live);
EventManager::getInstance()->sendEventImmediately(
std::make_shared<ScrapSelectionChangedEvent>(m_selectedScrap));
std::make_shared<DebrisSelectionChangedEvent>(m_selectedDebris));
}
}
@@ -1510,16 +1510,16 @@ void GameWorldView::drawSelectionHighlights(QPainter& painter)
painter.drawRect(rect->adjusted(-1, -1, 1, 1));
}
// A ring around each selected scrap pile, sitting just outside the pile's
// rendered circle (radius getTilePx()*0.2, matching drawScrap) (REQ-UI-SCRAP-CLICK-SELECT).
if (!m_selectedScrap.empty())
// A ring around each selected piece of debris, sitting just outside the debris's
// rendered circle (radius getTilePx()*0.2, matching drawDebris) (REQ-UI-DEBRIS-CLICK-SELECT).
if (!m_selectedDebris.empty())
{
const qreal outlineRadius = static_cast<qreal>(getTilePx() * 0.2f) + 3.0;
for (const ScrapInfo& scrap : m_sim->getScraps().getAllScrapInfo())
for (const DebrisInfo& debris : m_sim->getDebrisSystem().getAllDebrisInfo())
{
if (std::find(m_selectedScrap.begin(), m_selectedScrap.end(), scrap.entity)
== m_selectedScrap.end()) { continue; }
painter.drawEllipse(worldToWidget(scrap.position), outlineRadius, outlineRadius);
if (std::find(m_selectedDebris.begin(), m_selectedDebris.end(), debris.entity)
== m_selectedDebris.end()) { continue; }
painter.drawEllipse(worldToWidget(debris.position), outlineRadius, outlineRadius);
}
}
}
@@ -1646,12 +1646,12 @@ void GameWorldView::drawBeltItems(QPainter& painter)
});
}
void GameWorldView::drawScrap(QPainter& painter)
void GameWorldView::drawDebris(QPainter& painter)
{
const float r = getTilePx() * 0.2f;
for (const ScrapInfo& scrap : m_sim->getScraps().getAllScrapInfo())
for (const DebrisInfo& debris : m_sim->getDebrisSystem().getAllDebrisInfo())
{
const QPointF center = worldToWidget(scrap.position);
const QPointF center = worldToWidget(debris.position);
painter.setBrush(QColor(128, 110, 90));
painter.setPen(QPen(QColor(50, 40, 30), 1));
painter.drawEllipse(center,
@@ -1838,9 +1838,9 @@ void GameWorldView::drawDebugTargetLines(QPainter& painter)
[&](entt::entity /*e*/, const ShipIdentityComponent& si,
const PositionComponent& pos, const SalvageScrapBehavior& salvage)
{
if (!salvage.scrapTarget.has_value()) { return; }
if (!salvage.debrisTarget.has_value()) { return; }
drawTargetLine(si.schematicId, pos.value, *salvage.scrapTarget);
drawTargetLine(si.schematicId, pos.value, *salvage.debrisTarget);
});
}
@@ -2567,7 +2567,7 @@ void GameWorldView::mousePressEvent(QMouseEvent* event)
const bool ctrl = (event->modifiers() & Qt::ControlModifier) != 0;
const QVector2D worldPos = widgetToWorld(event->pos());
// Point hit-test precedence: buildings win over actors, which win over scrap
// Point hit-test precedence: buildings win over actors, which win over debris
// (REQ-UI-SELECTION-CATEGORIES).
std::optional<BuildingId> buildingHit = buildingAtTile(tile);
if (!buildingHit.has_value()) { buildingHit = siteAtTile(tile); }
@@ -2576,9 +2576,9 @@ void GameWorldView::mousePressEvent(QMouseEvent* event)
{
const BuildingId id = *buildingHit;
// A building selection is exclusive: it clears any field selection —
// actors and scrap — because buildings win (REQ-UI-SELECTION-CATEGORIES).
// actors and debris — because buildings win (REQ-UI-SELECTION-CATEGORIES).
clearEntitySelection();
clearScrapSelection();
clearDebrisSelection();
if (ctrl)
{
bool found = false;
@@ -2600,8 +2600,8 @@ void GameWorldView::mousePressEvent(QMouseEvent* event)
return;
}
// Selecting a field object (actor or scrap) clears any building selection but
// lets actors and scrap coexist (REQ-UI-SELECTION-CATEGORIES).
// Selecting a field object (actor or debris) clears any building selection but
// lets actors and debris coexist (REQ-UI-SELECTION-CATEGORIES).
const entt::entity actorHit = entityAtWorldPos(m_sim->getAdmin(), worldPos);
if (actorHit != entt::null)
{
@@ -2613,7 +2613,7 @@ void GameWorldView::mousePressEvent(QMouseEvent* event)
}
if (ctrl)
{
// Toggle this actor within the field selection, leaving scrap intact
// Toggle this actor within the field selection, leaving debris intact
// (REQ-UI-ENTITY-CLICK-SELECT).
bool found = false;
std::vector<entt::entity> newSel;
@@ -2629,15 +2629,15 @@ void GameWorldView::mousePressEvent(QMouseEvent* event)
{
// A plain click makes this actor the sole selection.
m_selectedEntities = { actorHit };
clearScrapSelection();
clearDebrisSelection();
}
EventManager::getInstance()->sendEventImmediately(
std::make_shared<EntitySelectionChangedEvent>(m_selectedEntities));
return;
}
if (const entt::entity scrapHit =
scrapAtWorldPos(m_sim->getAdmin(), worldPos); scrapHit != entt::null)
if (const entt::entity debrisHit =
debrisAtWorldPos(m_sim->getAdmin(), worldPos); debrisHit != entt::null)
{
if (!m_selectedBuildingIds.empty())
{
@@ -2647,26 +2647,26 @@ void GameWorldView::mousePressEvent(QMouseEvent* event)
}
if (ctrl)
{
// Toggle this pile within the field selection, leaving actors intact
// (REQ-UI-SCRAP-MULTI-SELECT).
// Toggle this debris within the field selection, leaving actors intact
// (REQ-UI-DEBRIS-MULTI-SELECT).
bool found = false;
std::vector<entt::entity> newSel;
for (entt::entity sel : m_selectedScrap)
for (entt::entity sel : m_selectedDebris)
{
if (sel == scrapHit) { found = true; }
if (sel == debrisHit) { found = true; }
else { newSel.push_back(sel); }
}
if (!found) { newSel.push_back(scrapHit); }
m_selectedScrap = newSel;
if (!found) { newSel.push_back(debrisHit); }
m_selectedDebris = newSel;
}
else
{
// A plain click makes this pile the sole selection.
m_selectedScrap = { scrapHit };
// A plain click makes this debris the sole selection.
m_selectedDebris = { debrisHit };
clearEntitySelection();
}
EventManager::getInstance()->sendEventImmediately(
std::make_shared<ScrapSelectionChangedEvent>(m_selectedScrap));
std::make_shared<DebrisSelectionChangedEvent>(m_selectedDebris));
return;
}
@@ -2681,7 +2681,7 @@ void GameWorldView::mousePressEvent(QMouseEvent* event)
std::make_shared<SelectionChangedEvent>(m_selectedBuildingIds));
}
clearEntitySelection();
clearScrapSelection();
clearDebrisSelection();
}
m_boxSelecting = true;
m_boxStartTile = tile;
@@ -2815,9 +2815,9 @@ void GameWorldView::mouseReleaseEvent(QMouseEvent* event)
if (!boxIds.empty())
{
// A box covering any building selects buildings; field objects (actors and
// scrap) in the box are ignored — buildings win (REQ-UI-MULTI-SELECT).
// debris) in the box are ignored — buildings win (REQ-UI-MULTI-SELECT).
clearEntitySelection();
clearScrapSelection();
clearDebrisSelection();
if (!ctrl)
{
m_selectedBuildingIds = boxIds;
@@ -2840,12 +2840,12 @@ void GameWorldView::mouseReleaseEvent(QMouseEvent* event)
}
// No buildings in the box: select the field objects it covers — ships, defence
// stations, and scrap together (REQ-UI-MULTI-SELECT, REQ-UI-SCRAP-MULTI-SELECT).
// stations, and debris together (REQ-UI-MULTI-SELECT, REQ-UI-DEBRIS-MULTI-SELECT).
const std::vector<entt::entity> boxActors =
actorsInBox(m_sim->getAdmin(), m_boxStartTile, m_boxCurrentTile);
const std::vector<entt::entity> boxScrap =
scrapInBox(m_sim->getAdmin(), m_boxStartTile, m_boxCurrentTile);
if (!boxActors.empty() || !boxScrap.empty())
const std::vector<entt::entity> boxDebris =
debrisInBox(m_sim->getAdmin(), m_boxStartTile, m_boxCurrentTile);
if (!boxActors.empty() || !boxDebris.empty())
{
if (!m_selectedBuildingIds.empty())
{
@@ -2856,7 +2856,7 @@ void GameWorldView::mouseReleaseEvent(QMouseEvent* event)
if (!ctrl)
{
m_selectedEntities = boxActors;
m_selectedScrap = boxScrap;
m_selectedDebris = boxDebris;
}
else
{
@@ -2869,20 +2869,20 @@ void GameWorldView::mouseReleaseEvent(QMouseEvent* event)
}
if (!found) { m_selectedEntities.push_back(e); }
}
for (entt::entity e : boxScrap)
for (entt::entity e : boxDebris)
{
bool found = false;
for (entt::entity sel : m_selectedScrap)
for (entt::entity sel : m_selectedDebris)
{
if (sel == e) { found = true; break; }
}
if (!found) { m_selectedScrap.push_back(e); }
if (!found) { m_selectedDebris.push_back(e); }
}
}
EventManager::getInstance()->sendEventImmediately(
std::make_shared<EntitySelectionChangedEvent>(m_selectedEntities));
EventManager::getInstance()->sendEventImmediately(
std::make_shared<ScrapSelectionChangedEvent>(m_selectedScrap));
std::make_shared<DebrisSelectionChangedEvent>(m_selectedDebris));
return;
}
@@ -2893,7 +2893,7 @@ void GameWorldView::mouseReleaseEvent(QMouseEvent* event)
EventManager::getInstance()->sendEventImmediately(
std::make_shared<SelectionChangedEvent>(m_selectedBuildingIds));
clearEntitySelection();
clearScrapSelection();
clearDebrisSelection();
}
}
}
@@ -3115,7 +3115,7 @@ void GameWorldView::resetForNewGame()
std::make_shared<DeconstructModeChangedEvent>(false));
m_selectedBuildingIds.clear();
clearEntitySelection();
clearScrapSelection();
clearDebrisSelection();
m_copiedConfig = std::nullopt;
m_copyConfigFlashes.clear();
m_boxSelecting = false;
@@ -3151,7 +3151,7 @@ void GameWorldView::handleEvent(std::shared_ptr<const BeamFiredEvent> event)
{
// Endpoint offset is a fraction of the target's visual size (REQ-SHP-FIRING-BEAM):
// half a ship's rendered radius, half a station's shorter footprint side, or
// half a scrap pile's rendered radius (scrap is drawn at getTilePx()*0.2).
// half a piece of debris's rendered radius (debris is drawn at getTilePx()*0.2).
float maxRadius = 0.125f;
if (m_sim->getAdmin().isValid(event->target)
&& m_sim->getAdmin().hasAll<StationBodyComponent>(event->target))
@@ -3161,7 +3161,7 @@ void GameWorldView::handleEvent(std::shared_ptr<const BeamFiredEvent> event)
maxRadius = shorter / 2.0f;
}
else if (m_sim->getAdmin().isValid(event->target)
&& m_sim->getAdmin().hasAll<ScrapDataComponent>(event->target))
&& m_sim->getAdmin().hasAll<DebrisComponent>(event->target))
{
maxRadius = 0.1f;
}