resolve mouse gestures through the action table too
This commit is contained in:
@@ -74,6 +74,23 @@
|
|||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// The action a left-button gesture triggers, with the Ctrl variant falling back to the
|
||||||
|
// plain one wherever nothing is bound to it. That fallback is what keeps Ctrl+click
|
||||||
|
// placing a building in builder mode and Ctrl+drag deconstructing an area: the modifier
|
||||||
|
// only means something where an action claims it (REQ-UI-CONTROLS-CONTENT).
|
||||||
|
ControlAction resolveLeftGesture(bool controlHeld, bool isDrag,
|
||||||
|
const ControlContext& context)
|
||||||
|
{
|
||||||
|
if (controlHeld)
|
||||||
|
{
|
||||||
|
const ControlAction action = resolveMouseAction(
|
||||||
|
isDrag ? MouseBinding::CtrlLeftDrag : MouseBinding::CtrlLeftClick, context);
|
||||||
|
if (action != ControlAction::None) { return action; }
|
||||||
|
}
|
||||||
|
return resolveMouseAction(isDrag ? MouseBinding::LeftDrag : MouseBinding::LeftClick,
|
||||||
|
context);
|
||||||
|
}
|
||||||
|
|
||||||
// Keep only the filter entries whose item type is currently unlocked
|
// Keep only the filter entries whose item type is currently unlocked
|
||||||
// (REQ-LOCK-UI-BLUEPRINT). An empty result means "accept all".
|
// (REQ-LOCK-UI-BLUEPRINT). An empty result means "accept all".
|
||||||
std::vector<ItemType> filterUnlockedItems(const std::vector<ItemType>& filter,
|
std::vector<ItemType> filterUnlockedItems(const std::vector<ItemType>& filter,
|
||||||
@@ -1142,33 +1159,47 @@ ControlContext GameWorldView::getControlContext() const
|
|||||||
void GameWorldView::mousePressEvent(QMouseEvent* event)
|
void GameWorldView::mousePressEvent(QMouseEvent* event)
|
||||||
{
|
{
|
||||||
const WorldCoordinates coordinates = getCoordinates();
|
const WorldCoordinates coordinates = getCoordinates();
|
||||||
|
const ControlContext context = getControlContext();
|
||||||
|
|
||||||
if (event->button() != Qt::LeftButton)
|
if (event->button() != Qt::LeftButton)
|
||||||
{
|
{
|
||||||
if (event->button() == Qt::RightButton)
|
if (event->button() == Qt::RightButton)
|
||||||
{
|
{
|
||||||
if (m_buildMode.isBuilderMode() && m_buildMode.isDraggingBelt())
|
switch (resolveMouseAction(MouseBinding::RightClick, context))
|
||||||
{
|
{
|
||||||
// Cancel the in-progress belt drag without placing anything;
|
case ControlAction::CancelBeltLine:
|
||||||
// stay in belt builder mode (REQ-BLD-BELT-DRAG).
|
// Drop the in-progress path without placing anything; belt builder
|
||||||
|
// mode stays active (REQ-BLD-BELT-DRAG).
|
||||||
m_buildMode.cancelBeltDrag();
|
m_buildMode.cancelBeltDrag();
|
||||||
}
|
break;
|
||||||
else if (m_buildMode.getMode() != BuildMode::None)
|
case ControlAction::ExitMode:
|
||||||
{
|
|
||||||
m_buildMode.exitCurrentMode();
|
m_buildMode.exitCurrentMode();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const QPoint tile = coordinates.widgetToTile(event->pos());
|
const QPoint tile = coordinates.widgetToTile(event->pos());
|
||||||
|
const bool controlHeld = (event->modifiers() & Qt::ControlModifier) != 0;
|
||||||
|
|
||||||
if (m_buildMode.isBuilderMode())
|
// A press begins the click gesture; whether it turns out to be a drag is settled on
|
||||||
|
// release, where the drag binding is resolved instead.
|
||||||
|
switch (resolveLeftGesture(controlHeld, /*isDrag*/ false, context))
|
||||||
{
|
{
|
||||||
if (m_buildMode.getBuilderType() == BuildingType::Belt)
|
case ControlAction::Place:
|
||||||
|
case ControlAction::ApplySettings:
|
||||||
|
if (m_buildMode.isBlueprintMode())
|
||||||
{
|
{
|
||||||
// Deferred placement: start the drag and show the path ghost; nothing
|
placeBlueprintAtTile(tile);
|
||||||
// is placed until release (REQ-BLD-BELT-DRAG).
|
}
|
||||||
|
else if (m_buildMode.getBuilderType() == BuildingType::Belt)
|
||||||
|
{
|
||||||
|
// Belts place by dragging, so the press only anchors the path and shows its
|
||||||
|
// ghost; nothing is placed until release, and a plain click is the one-tile
|
||||||
|
// case (REQ-BLD-BELT-DRAG).
|
||||||
m_buildMode.beginBeltDrag(tile);
|
m_buildMode.beginBeltDrag(tile);
|
||||||
m_cursorWorldPos = coordinates.widgetToWorld(event->pos());
|
m_cursorWorldPos = coordinates.widgetToWorld(event->pos());
|
||||||
recomputeBeltDragPath(tile);
|
recomputeBeltDragPath(tile);
|
||||||
@@ -1177,27 +1208,22 @@ void GameWorldView::mousePressEvent(QMouseEvent* event)
|
|||||||
{
|
{
|
||||||
placeAtTile(tile);
|
placeAtTile(tile);
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
else if (m_buildMode.isBlueprintMode())
|
|
||||||
{
|
case ControlAction::ToggleDeconstruct:
|
||||||
placeBlueprintAtTile(tile);
|
|
||||||
}
|
|
||||||
else if (m_buildMode.isDeconstructMode())
|
|
||||||
{
|
|
||||||
// Start a deconstruct box drag; a plain click resolves as a 1x1 box on
|
// Start a deconstruct box drag; a plain click resolves as a 1x1 box on
|
||||||
// release (REQ-BLD-DECONSTRUCT-CLICK, REQ-BLD-DECONSTRUCT-BOX).
|
// release (REQ-BLD-DECONSTRUCT-CLICK, REQ-BLD-DECONSTRUCT-BOX).
|
||||||
m_boxSelecting = true;
|
m_boxSelecting = true;
|
||||||
m_boxStartTile = tile;
|
m_boxStartTile = tile;
|
||||||
m_boxCurrentTile = tile;
|
m_boxCurrentTile = tile;
|
||||||
}
|
break;
|
||||||
else
|
|
||||||
{
|
|
||||||
const bool ctrl = (event->modifiers() & Qt::ControlModifier) != 0;
|
|
||||||
|
|
||||||
|
case ControlAction::Select:
|
||||||
|
case ControlAction::AddToSelection:
|
||||||
// Only a click that hit nothing starts a box drag. Starting one on a hit
|
// 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
|
// 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.
|
// click: a Ctrl+click would toggle the building off, then straight back on.
|
||||||
if (!selectAtPoint(tile, coordinates.widgetToWorld(event->pos()), ctrl))
|
if (!selectAtPoint(tile, coordinates.widgetToWorld(event->pos()), controlHeld))
|
||||||
{
|
{
|
||||||
// selectAtPoint has already cleared the selection unless Ctrl is
|
// selectAtPoint has already cleared the selection unless Ctrl is
|
||||||
// preserving it for an additive drag.
|
// preserving it for an additive drag.
|
||||||
@@ -1205,6 +1231,10 @@ void GameWorldView::mousePressEvent(QMouseEvent* event)
|
|||||||
m_boxStartTile = tile;
|
m_boxStartTile = tile;
|
||||||
m_boxCurrentTile = tile;
|
m_boxCurrentTile = tile;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1347,7 +1377,11 @@ void GameWorldView::mouseReleaseEvent(QMouseEvent* event)
|
|||||||
const std::vector<BuildingId> boxIds =
|
const std::vector<BuildingId> boxIds =
|
||||||
buildingsInBox(m_sim->getFactoryState(), m_boxStartTile, m_boxCurrentTile);
|
buildingsInBox(m_sim->getFactoryState(), m_boxStartTile, m_boxCurrentTile);
|
||||||
|
|
||||||
if (m_buildMode.isDeconstructMode())
|
const bool controlHeld = (event->modifiers() & Qt::ControlModifier) != 0;
|
||||||
|
const ControlAction dragAction =
|
||||||
|
resolveLeftGesture(controlHeld, /*isDrag*/ true, getControlContext());
|
||||||
|
|
||||||
|
if (dragAction == ControlAction::DeconstructArea)
|
||||||
{
|
{
|
||||||
const FactoryState& factory = m_sim->getFactoryState();
|
const FactoryState& factory = m_sim->getFactoryState();
|
||||||
|
|
||||||
@@ -1409,7 +1443,9 @@ void GameWorldView::mouseReleaseEvent(QMouseEvent* event)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
selectInBox((event->modifiers() & Qt::ControlModifier) != 0);
|
// A Ctrl box adds and never deselects, where a plain one replaces
|
||||||
|
// (REQ-UI-MULTI-SELECT).
|
||||||
|
selectInBox(dragAction == ControlAction::AddAreaToSelection);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user