/* ScummVM - Graphic Adventure Engine * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT * file distributed with this source distribution. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * */ #ifndef COMMON_HARDWARE_KEY_H #define COMMON_HARDWARE_KEY_H #include "common/scummsys.h" #include "common/array.h" #include "common/events.h" #include "common/keyboard.h" #include "common/str.h" namespace Common { typedef uint32 HardwareInputCode; enum HardwareInputType { /** Empty / invalid input type */ kHardwareInputTypeInvalid, /** Keyboard input that sends -up and -down events */ kHardwareInputTypeKeyboard, /** Mouse input that sends -up and -down events */ kHardwareInputTypeMouse, /** Joystick input that sends -up and -down events */ kHardwareInputTypeJoystickButton, /** Joystick input that sends "analog" values */ kHardwareInputTypeJoystickHalfAxis, /** Input that sends single events */ kHardwareInputTypeCustom }; /** * Describes an available hardware input */ struct HardwareInput { /** unique id used for saving/loading to config */ String id; /** Human readable description */ U32String description; /** Type tag */ HardwareInputType type; /** * A platform specific unique identifier for an input event * generated when this input is triggered. * This is only relevant when type == kHardwareInputTypeGeneric */ HardwareInputCode inputCode; /** * The KeyState that is generated by the back-end * when this hardware key is pressed. * This is only relevant when type == kHardwareInputTypeKeyboard */ KeyState key; HardwareInput() : inputCode(0), type(kHardwareInputTypeInvalid) { } static HardwareInput createCustom(const String &i, HardwareInputCode ic, const U32String &desc) { return createSimple(kHardwareInputTypeCustom, i, ic, desc); } static HardwareInput createKeyboard(const String &i, KeyState ky, const U32String &desc) { HardwareInput hardwareInput; hardwareInput.id = i; hardwareInput.description = desc; hardwareInput.type = kHardwareInputTypeKeyboard; hardwareInput.inputCode = 0; hardwareInput.key = ky; return hardwareInput; } static HardwareInput createJoystickButton(const String &i, uint8 button, const U32String &desc) { return createSimple(kHardwareInputTypeJoystickButton, i, button, desc); } static HardwareInput createJoystickHalfAxis(const String &i, uint8 axis, bool positiveHalf, const U32String &desc) { return createSimple(kHardwareInputTypeJoystickHalfAxis, i, axis * 2 + (positiveHalf ? 1 : 0), desc); } static HardwareInput createMouse(const String &i, uint8 button, const U32String &desc) { return createSimple(kHardwareInputTypeMouse, i, button, desc); } private: static HardwareInput createSimple(HardwareInputType type, const String &i, HardwareInputCode ic, const U32String &desc) { HardwareInput hardwareInput; hardwareInput.id = i; hardwareInput.description = desc; hardwareInput.type = type; hardwareInput.inputCode = ic; return hardwareInput; } }; /** * Entry in a static table of custom backend hardware inputs */ struct HardwareInputTableEntry { const char *hwId; HardwareInputCode code; const char *desc; static const HardwareInputTableEntry *findWithCode(const HardwareInputTableEntry *_entries, HardwareInputCode code) { for (const HardwareInputTableEntry *hw = _entries; hw->hwId; hw++) { if (hw->code == code) { return hw; } } return nullptr; } static const HardwareInputTableEntry *findWithId(const HardwareInputTableEntry *_entries, const String &id) { for (const HardwareInputTableEntry *hw = _entries; hw->hwId; hw++) { if (id.equals(hw->hwId)) { return hw; } } return nullptr; } }; /** * Entry in a static table of available non-modifier keys */ struct KeyTableEntry { const char *hwId; KeyCode keycode; const char *desc; }; /** * Entry in a static table of available key modifiers */ struct ModifierTableEntry { byte flag; const char *id; const char *desc; }; enum AxisType { /** An axis that sends "analog" values from JOYAXIS_MIN to JOYAXIS_MAX. e.g. a gamepad stick axis */ kAxisTypeFull, /** An axis that sends "analog" values from 0 to JOYAXIS_MAX. e.g. a gamepad trigger */ kAxisTypeHalf }; struct AxisTableEntry { const char *hwId; HardwareInputCode code; AxisType type; const char *desc; static const AxisTableEntry *findWithCode(const AxisTableEntry *_entries, HardwareInputCode code) { for (const AxisTableEntry *hw = _entries; hw->hwId; hw++) { if (hw->code == code) { return hw; } } return nullptr; } static const AxisTableEntry *findWithId(const AxisTableEntry *_entries, const String &id) { for (const AxisTableEntry *hw = _entries; hw->hwId; hw++) { if (id.equals(hw->hwId)) { return hw; } } return nullptr; } }; /** * Interface for querying information about a hardware input device */ class HardwareInputSet { public: virtual ~HardwareInputSet(); /** * Retrieve a hardware input description from an unique identifier * * In case no input was found with the specified id, an empty * HardwareInput structure is return with the type set to * kHardwareInputTypeInvalid. */ virtual HardwareInput findHardwareInput(const String &id) const = 0; /** * Retrieve a hardware input description from one of the events * produced when the input is triggered. * * In case the specified event is not produced by this device, * an empty HardwareInput structure is return with the type set to * kHardwareInputTypeInvalid. */ virtual HardwareInput findHardwareInput(const Event &event) const = 0; }; /** * A keyboard input device * * Describes the keys and key + modifiers combinations as HardwareInputs */ class KeyboardHardwareInputSet : public HardwareInputSet { public: KeyboardHardwareInputSet(const KeyTableEntry *keys, const ModifierTableEntry *modifiers); // HardwareInputSet API HardwareInput findHardwareInput(const String &id) const override; HardwareInput findHardwareInput(const Event &event) const override; /** Transform a keystate into a canonical form that can be used to unambiguously identify the keypress */ static KeyState normalizeKeyState(const KeyState &keystate); private: const KeyTableEntry *_keys; const ModifierTableEntry *_modifiers; }; /** * A mouse input device * * Describes the mouse buttons */ class MouseHardwareInputSet : public HardwareInputSet { public: MouseHardwareInputSet(const HardwareInputTableEntry *buttonEntries); // HardwareInputSet API HardwareInput findHardwareInput(const String &id) const override; HardwareInput findHardwareInput(const Event &event) const override; private: const HardwareInputTableEntry *_buttonEntries; }; /** * A joystick input device */ class JoystickHardwareInputSet : public HardwareInputSet { public: JoystickHardwareInputSet(const HardwareInputTableEntry *buttonEntries, const AxisTableEntry *axisEntries); // HardwareInputSet API HardwareInput findHardwareInput(const String &id) const override; HardwareInput findHardwareInput(const Event &event) const override; private: const HardwareInputTableEntry *_buttonEntries; const AxisTableEntry *_axisEntries; }; /** * A custom backend input device * * @todo This is currently unused. Perhaps it should be removed. */ class CustomHardwareInputSet : public HardwareInputSet { public: CustomHardwareInputSet(const HardwareInputTableEntry *hardwareEntries); // HardwareInputSet API HardwareInput findHardwareInput(const String &id) const override; HardwareInput findHardwareInput(const Event &event) const override; private: const HardwareInputTableEntry *_hardwareEntries; }; /** * A composite input device that delegates to a set of actual input devices. */ class CompositeHardwareInputSet : public HardwareInputSet { public: ~CompositeHardwareInputSet() override; // HardwareInputSet API HardwareInput findHardwareInput(const String &id) const override; HardwareInput findHardwareInput(const Event &event) const override; /** * Add an input device to this composite device * * Takes ownership of the hardware input set */ void addHardwareInputSet(HardwareInputSet *hardwareInputSet); private: Array _inputSets; }; /** A standard set of keyboard keys */ extern const KeyTableEntry defaultKeys[]; /** A standard set of keyboard modifiers */ extern const ModifierTableEntry defaultModifiers[]; /** A standard set of mouse buttons */ extern const HardwareInputTableEntry defaultMouseButtons[]; /** A standard set of joystick buttons based on the ScummVM event model */ extern const HardwareInputTableEntry defaultJoystickButtons[]; /** A standard set of joystick axes based on the ScummVM event model */ extern const AxisTableEntry defaultJoystickAxes[]; } // End of namespace Common #endif // #ifndef COMMON_HARDWARE_KEY_H