Scrap piles become a third selection category: click to select (actors win on overlap), box-drag / Ctrl+click multi-select, and the selected- object panel shows the summed remaining amount, updating live and dropping piles as they are collected or despawn. - ScrapSystem: expose per-pile amount via ScrapInfo. - EntityHitTest: add scrapAtWorldPos and scrapInBox (with tests). - New header-only ScrapSelectionChangedEvent. - GameWorldView: scrap selection member, click/box handling with the building-wins disambiguation, and per-frame pruning of gone piles. - SelectedBuildingPanel: scrap event, "Scrap: N" label, live total; scrap and building/entity selections clear each other. Implements REQ-UI-SCRAP-CLICK-SELECT, REQ-UI-SCRAP-MULTI-SELECT, REQ-UI-SCRAP-PANEL. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DZR44tA8sn4dPqDzAVXyps
79 lines
1.8 KiB
C++
79 lines
1.8 KiB
C++
#include "ScrapSystem.h"
|
|
|
|
#include "DespawnAtComponent.h"
|
|
#include "EntityAdmin.h"
|
|
#include "PositionComponent.h"
|
|
#include "ScrapDataComponent.h"
|
|
#include "tracing.h"
|
|
|
|
ScrapSystem::ScrapSystem(EntityAdmin& admin)
|
|
: m_admin(admin)
|
|
{
|
|
}
|
|
|
|
entt::entity ScrapSystem::spawn(QVector2D position, int amount, Tick despawnAt)
|
|
{
|
|
return m_admin.spawnScrap(position, amount, despawnAt);
|
|
}
|
|
|
|
void ScrapSystem::tickDespawn(Tick currentTick)
|
|
{
|
|
TRACE();
|
|
std::vector<entt::entity> expired;
|
|
m_admin.forEach<DespawnAtComponent>(
|
|
[&expired, currentTick](entt::entity e, DespawnAtComponent& d)
|
|
{
|
|
if (d.tick <= currentTick)
|
|
{
|
|
expired.push_back(e);
|
|
}
|
|
});
|
|
|
|
for (entt::entity e : expired)
|
|
{
|
|
m_admin.destroy(e);
|
|
}
|
|
}
|
|
|
|
std::optional<int> ScrapSystem::consume(entt::entity entity)
|
|
{
|
|
if (!m_admin.isValid(entity) || !m_admin.hasAll<ScrapDataComponent>(entity))
|
|
{
|
|
return std::nullopt;
|
|
}
|
|
int amount = m_admin.get<ScrapDataComponent>(entity).amount;
|
|
m_admin.destroy(entity);
|
|
return amount;
|
|
}
|
|
|
|
bool ScrapSystem::collectOne(entt::entity entity)
|
|
{
|
|
if (!m_admin.isValid(entity) || !m_admin.hasAll<ScrapDataComponent>(entity))
|
|
{
|
|
return false;
|
|
}
|
|
ScrapDataComponent& data = m_admin.get<ScrapDataComponent>(entity);
|
|
if (data.amount <= 0)
|
|
{
|
|
return false;
|
|
}
|
|
--data.amount;
|
|
if (data.amount <= 0)
|
|
{
|
|
m_admin.destroy(entity);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
std::vector<ScrapInfo> ScrapSystem::allScrapInfo() const
|
|
{
|
|
std::vector<ScrapInfo> result;
|
|
m_admin.forEach<ScrapDataComponent>(
|
|
[&result, this](entt::entity e, const ScrapDataComponent& sd)
|
|
{
|
|
result.push_back(ScrapInfo{e, m_admin.get<PositionComponent>(e).value, sd.amount});
|
|
});
|
|
return result;
|
|
}
|
|
|