fix Ctrl+click no longer deselecting
Regression from the SelectionController extraction. The original started a box drag only in the empty-space branch, after the building, actor and debris hits had each returned. Pulling the hit resolution out into selectAtPoint left the box drag behind as unconditional, so every click started one. That made a click on an object resolve twice: once on press, and again on release as a 1x1 box over the same tile. For a plain click both resolutions are Replace with the same object, so nothing looked wrong. For Ctrl+click the second resolution toggled the object straight back on, so it never deselected - and the selection rectangle drawn during the drag is the box that should not have been started. selectAtPoint now reports whether it hit anything, and only a click that hit nothing starts a box drag. The SelectionController itself was correct, and its tests still pass: the bug was entirely in the widget wiring, which nothing on this branch can test. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JcReq7hVk4KUPhTDKWAG7K
This commit is contained in:
@@ -1074,17 +1074,21 @@ void GameWorldView::mousePressEvent(QMouseEvent* event)
|
||||
|
||||
const bool ctrl = (event->modifiers() & Qt::ControlModifier) != 0;
|
||||
|
||||
selectAtPoint(tile, coordinates.widgetToWorld(event->pos()), ctrl);
|
||||
|
||||
// A click on empty space also starts a box drag. selectAtPoint has already
|
||||
// cleared the selection unless Ctrl is preserving it for an additive drag.
|
||||
// Only a click that hit nothing starts a box drag. Starting one on a hit
|
||||
// would re-resolve the same object as a 1x1 box on release and undo the
|
||||
// click: a Ctrl+click would toggle the building off, then straight back on.
|
||||
if (!selectAtPoint(tile, coordinates.widgetToWorld(event->pos()), ctrl))
|
||||
{
|
||||
// selectAtPoint has already cleared the selection unless Ctrl is
|
||||
// preserving it for an additive drag.
|
||||
m_boxSelecting = true;
|
||||
m_boxStartTile = tile;
|
||||
m_boxCurrentTile = tile;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GameWorldView::selectAtPoint(QPoint tile, QVector2D worldPos, bool additive)
|
||||
bool GameWorldView::selectAtPoint(QPoint tile, QVector2D worldPos, bool additive)
|
||||
{
|
||||
// Point hit-test precedence: buildings win over actors, which win over debris
|
||||
// (REQ-UI-SELECTION-CATEGORIES). What each hit then does to the existing
|
||||
@@ -1096,25 +1100,26 @@ void GameWorldView::selectAtPoint(QPoint tile, QVector2D worldPos, bool additive
|
||||
if (buildingHit.has_value())
|
||||
{
|
||||
m_selection.selectBuildings({*buildingHit}, mode);
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
const entt::entity actorHit = entityAtWorldPos(m_sim->getAdmin(), worldPos);
|
||||
if (actorHit != entt::null)
|
||||
{
|
||||
m_selection.selectFieldObjects({actorHit}, {}, mode);
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
const entt::entity debrisHit = debrisAtWorldPos(m_sim->getAdmin(), worldPos);
|
||||
if (debrisHit != entt::null)
|
||||
{
|
||||
m_selection.selectFieldObjects({}, {debrisHit}, mode);
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Empty space: a plain click clears the whole selection, Ctrl preserves it.
|
||||
if (!additive) { m_selection.clearAll(); }
|
||||
return false;
|
||||
}
|
||||
|
||||
void GameWorldView::selectInBox(bool additive)
|
||||
|
||||
@@ -193,8 +193,9 @@ private:
|
||||
void pruneDespawnedActors();
|
||||
// Resolves a click into the selection it should produce, applying the category
|
||||
// precedence of REQ-UI-SELECTION-CATEGORIES; the controller owns what that then
|
||||
// does to the existing selection.
|
||||
void selectAtPoint(QPoint tile, QVector2D worldPos, bool additive);
|
||||
// does to the existing selection. Returns false when the click hit nothing,
|
||||
// which is the only case that goes on to start a box drag.
|
||||
bool selectAtPoint(QPoint tile, QVector2D worldPos, bool additive);
|
||||
void selectInBox(bool additive);
|
||||
void stepSpeed(int delta);
|
||||
void placeAtTile(QPoint tile);
|
||||
|
||||
Reference in New Issue
Block a user