#pragma once #include #include "BuildingType.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; the bindings themselves are still hard-coded // here for now. // // 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. bool handleKeyPress(QKeyEvent* event); bool handleKeyRelease(QKeyEvent* event); // 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; };