60 lines
2.6 KiB
C++
60 lines
2.6 KiB
C++
#pragma once
|
|
|
|
#include <QString>
|
|
|
|
#include "BuildingType.h"
|
|
#include "ControlAction.h"
|
|
#include "WorldCamera.h"
|
|
|
|
class QKeyEvent;
|
|
|
|
// Turns raw key events into the game's semantic actions and publishes them
|
|
// (REQ-UI-HOTKEYS). Widgets react to the action, never to the key, so the two can
|
|
// be rebound independently later.
|
|
//
|
|
// Which key means what is not decided here: the caller hands in a ControlContext and
|
|
// ControlAction.h resolves the press against it, so this file only knows what each
|
|
// action means once resolved. That is what keeps the controls panel and the key
|
|
// handling from drifting apart -- both read the one table (REQ-UI-CONTROLS-ACCURACY).
|
|
//
|
|
// Two output shapes, chosen by the nature of the action rather than by taste:
|
|
//
|
|
// * Discrete actions — one press, one thing happens — fire an event as they
|
|
// always have.
|
|
// * Continuous actions, currently just panning, are held state. They also travel
|
|
// as events, but level-triggered ones carrying the complete current value (see
|
|
// PanDirectionChangedEvent), so a receiver never has to reconstruct state from
|
|
// edges.
|
|
//
|
|
// Holding the state here rather than in the widgets is what makes releaseAll()
|
|
// possible: one call clears every held action at once, which is how a lost key-up
|
|
// (focus moving to a modal mid-pan) stops being a stuck input.
|
|
class InputMapper
|
|
{
|
|
public:
|
|
// The build hotkey that selects the given building type, spelled for display on
|
|
// its build button's badge (REQ-UI-BUILD-COST): "1" for a plain digit, "⇧1" for
|
|
// a Shift+digit, and an empty string for a building type with no build hotkey.
|
|
// Lives here so the badge and the key handling read the same binding table.
|
|
static QString getBuildHotkeyLabel(BuildingType type);
|
|
|
|
// Both return true when the key was consumed; the caller passes anything else
|
|
// on to its base class so unrelated shortcuts keep working. `context` is the
|
|
// player's current situation, which decides what a key does (REQ-UI-CONTROLS-CONTENT).
|
|
bool handleKeyPress(QKeyEvent* event, const ControlContext& context);
|
|
bool handleKeyRelease(QKeyEvent* event, const ControlContext& context);
|
|
|
|
// Drops all held-key state, publishing the resulting change. Call when the
|
|
// receiving widget can no longer expect key-up events.
|
|
void releaseAll();
|
|
|
|
private:
|
|
// Recomputes the pan direction from the held keys and publishes it if it
|
|
// changed. Holding both keys cancels out.
|
|
void updatePanDirection();
|
|
|
|
bool m_panLeftHeld = false;
|
|
bool m_panRightHeld = false;
|
|
PanDirection m_panDirection = PanDirection::None;
|
|
};
|