place the selection panel beside what it describes

This commit is contained in:
2026-08-09 13:45:04 +02:00
parent 7ae5f8c4dc
commit c0b009c548
25 changed files with 789 additions and 182 deletions

View File

@@ -47,6 +47,8 @@
#include "ItemIconCache.h"
#include "PositionComponent.h"
#include "DebrisSystem.h"
#include "SelectionAnchorChangedEvent.h"
#include "SelectionBounds.h"
#include "SelectionChangedEvent.h"
#include "ShipIdentityComponent.h"
#include "ShipSystem.h"
@@ -1255,6 +1257,7 @@ bool GameWorldView::selectAtPoint(QPoint tile, QVector2D worldPos, bool additive
if (!buildingHit.has_value()) { buildingHit = siteAtTile(tile); }
if (buildingHit.has_value())
{
publishSelectionAnchor(mode, {*buildingHit}, {}, {});
m_selection.selectBuildings({*buildingHit}, mode);
return true;
}
@@ -1262,6 +1265,7 @@ bool GameWorldView::selectAtPoint(QPoint tile, QVector2D worldPos, bool additive
const entt::entity actorHit = entityAtWorldPos(m_sim->getAdmin(), worldPos);
if (actorHit != entt::null)
{
publishSelectionAnchor(mode, {}, {actorHit}, {});
m_selection.selectFieldObjects({actorHit}, {}, mode);
return true;
}
@@ -1269,6 +1273,7 @@ bool GameWorldView::selectAtPoint(QPoint tile, QVector2D worldPos, bool additive
const entt::entity debrisHit = debrisAtWorldPos(m_sim->getAdmin(), worldPos);
if (debrisHit != entt::null)
{
publishSelectionAnchor(mode, {}, {}, {debrisHit});
m_selection.selectFieldObjects({}, {debrisHit}, mode);
return true;
}
@@ -1289,6 +1294,7 @@ void GameWorldView::selectInBox(bool additive)
buildingsInBox(m_sim->getFactoryState(), m_boxStartTile, m_boxCurrentTile);
if (!boxIds.empty())
{
publishSelectionAnchor(mode, boxIds, {}, {});
m_selection.selectBuildings(boxIds, mode);
return;
}
@@ -1299,6 +1305,7 @@ void GameWorldView::selectInBox(bool additive)
debrisInBox(m_sim->getAdmin(), m_boxStartTile, m_boxCurrentTile);
if (!boxActors.empty() || !boxDebris.empty())
{
publishSelectionAnchor(mode, {}, boxActors, boxDebris);
m_selection.selectFieldObjects(boxActors, boxDebris, mode);
return;
}
@@ -1307,6 +1314,35 @@ void GameWorldView::selectInBox(bool additive)
if (!additive) { m_selection.clearAll(); }
}
void GameWorldView::publishSelectionAnchor(SelectionMode mode,
const std::vector<BuildingId>& buildings,
const std::vector<entt::entity>& actors,
const std::vector<entt::entity>& debris)
{
// An additive gesture onto something already selected is growing that selection, not
// starting one, and the panel stays where it was put (REQ-UI-SELECTION-PANEL).
const bool startsSelection =
(mode == SelectionMode::Replace) || (m_selection.getSelectedBuildings().empty()
&& m_selection.getSelectedActors().empty()
&& m_selection.getSelectedDebris().empty());
if (!startsSelection)
{
return;
}
// Screen space, frozen here: the panel is placed against where the selection is at
// this moment and stays there, however far the view scrolls or the objects move
// afterwards.
const QRect anchorRect = getSelectionWidgetRect(*m_sim, getCoordinates(),
buildings, actors, debris);
if (anchorRect.isNull())
{
return;
}
EventManager::getInstance()->sendEventImmediately(
std::make_shared<SelectionAnchorChangedEvent>(anchorRect));
}
void GameWorldView::mouseMoveEvent(QMouseEvent* event)
{
const WorldCoordinates coordinates = getCoordinates();