| 1 | //************************************ bs::framework - Copyright 2018 Marko Pintera **************************************// |
| 2 | //*********** Licensed under the MIT license. See LICENSE.md for full terms. This notice is not to be removed. ***********// |
| 3 | #pragma once |
| 4 | |
| 5 | #include "BsPrerequisites.h" |
| 6 | #include "Utility/BsModule.h" |
| 7 | #include "Input/BsInputConfiguration.h" |
| 8 | #include "Utility/BsDynArray.h" |
| 9 | |
| 10 | namespace bs |
| 11 | { |
| 12 | /** @addtogroup Input-Engine |
| 13 | * @{ |
| 14 | */ |
| 15 | |
| 16 | /** |
| 17 | * Handles virtual input that allows you to receive virtual input events that hide the actual physical input, allowing |
| 18 | * you to easily change the input keys while being transparent to the external code. |
| 19 | */ |
| 20 | class BS_EXPORT VirtualInput : public Module<VirtualInput> |
| 21 | { |
| 22 | /** Possible states of virtual buttons. */ |
| 23 | enum class ButtonState |
| 24 | { |
| 25 | Off, |
| 26 | On, |
| 27 | ToggledOn, |
| 28 | ToggledOff |
| 29 | }; |
| 30 | |
| 31 | /** Data container for a single virtual button. */ |
| 32 | struct ButtonData |
| 33 | { |
| 34 | VirtualButton button; |
| 35 | ButtonState state; |
| 36 | UINT64 timestamp; |
| 37 | UINT64 updateFrameIdx; |
| 38 | bool allowRepeat; |
| 39 | }; |
| 40 | |
| 41 | /** Contains button data for a specific input device. */ |
| 42 | struct DeviceData |
| 43 | { |
| 44 | Map<UINT32, ButtonData> cachedStates; |
| 45 | DynArray<UINT32> heldButtons; |
| 46 | }; |
| 47 | |
| 48 | /** Data container for a virtual button event. */ |
| 49 | struct VirtualButtonEvent |
| 50 | { |
| 51 | VirtualButton button; |
| 52 | ButtonState state; |
| 53 | UINT32 deviceIdx; |
| 54 | }; |
| 55 | |
| 56 | public: |
| 57 | VirtualInput(); |
| 58 | |
| 59 | /** Creates a new empty input configuration. */ |
| 60 | static SPtr<InputConfiguration> createConfiguration(); |
| 61 | |
| 62 | /** Sets an input configuration that determines how physical keys map to virtual buttons. */ |
| 63 | void setConfiguration(const SPtr<InputConfiguration>& input); |
| 64 | |
| 65 | /** Retrieves the active input configuration that determines how physical keys map to virtual buttons. */ |
| 66 | SPtr<InputConfiguration> getConfiguration() const { return mInputConfiguration; } |
| 67 | |
| 68 | /** |
| 69 | * Check is the virtual button just getting pressed. This state is only active for one frame. |
| 70 | * |
| 71 | * @param[in] button Virtual button identifier. |
| 72 | * @param[in] deviceIdx Optional device index in case multiple input devices are available. |
| 73 | */ |
| 74 | bool isButtonDown(const VirtualButton& button, UINT32 deviceIdx = 0) const; |
| 75 | |
| 76 | /** |
| 77 | * Check is the virtual button just getting released. This state is only active for one frame. |
| 78 | * |
| 79 | * @param[in] button Virtual button identifier. |
| 80 | * @param[in] deviceIdx Optional device index in case multiple input devices are available. |
| 81 | */ |
| 82 | bool isButtonUp(const VirtualButton& button, UINT32 deviceIdx = 0) const; |
| 83 | |
| 84 | /** |
| 85 | * Check is the virtual button is being held. This state is active as long as the button is being held down, |
| 86 | * possibly for multiple frames. |
| 87 | * |
| 88 | * @param[in] button Virtual button identifier. |
| 89 | * @param[in] deviceIdx Optional device index in case multiple input devices are available. |
| 90 | */ |
| 91 | bool isButtonHeld(const VirtualButton& button, UINT32 deviceIdx = 0) const; |
| 92 | |
| 93 | /** |
| 94 | * Returns normalized value for the specified input axis. Returned value will usually be in [-1.0, 1.0] range, but |
| 95 | * can be outside the range for devices with unbound axes (for example mouse). |
| 96 | * |
| 97 | * @param[in] axis Virtual axis identifier. |
| 98 | * @param[in] deviceIdx Optional device index in case multiple input devices are available. |
| 99 | */ |
| 100 | float getAxisValue(const VirtualAxis& axis, UINT32 deviceIdx = 0) const; |
| 101 | |
| 102 | /** Triggered when a virtual button is pressed. */ |
| 103 | Event<void(const VirtualButton&, UINT32 deviceIdx)> onButtonDown; |
| 104 | |
| 105 | /** Triggered when a virtual button is released. */ |
| 106 | Event<void(const VirtualButton&, UINT32 deviceIdx)> onButtonUp; |
| 107 | |
| 108 | /** Triggered every frame when a virtual button is being held down. */ |
| 109 | Event<void(const VirtualButton&, UINT32 deviceIdx)> onButtonHeld; |
| 110 | |
| 111 | /** @name Internal |
| 112 | * @{ |
| 113 | */ |
| 114 | |
| 115 | /** Called once every frame. Triggers button callbacks. */ |
| 116 | void _update(); |
| 117 | |
| 118 | /** @} */ |
| 119 | private: |
| 120 | friend class VirtualButton; |
| 121 | |
| 122 | /** Performs all logic related to a button press. */ |
| 123 | void buttonDown(const ButtonEvent& event); |
| 124 | |
| 125 | /** Performs all logic related to a button release. */ |
| 126 | void buttonUp(const ButtonEvent& event); |
| 127 | |
| 128 | SPtr<InputConfiguration> mInputConfiguration; |
| 129 | Vector<DeviceData> mDevices; |
| 130 | Queue<VirtualButtonEvent> mEvents; |
| 131 | UINT32 mActiveModifiers = (UINT32)ButtonModifier::None; |
| 132 | |
| 133 | // Transient |
| 134 | Vector<VirtualButton> tempButtons; |
| 135 | Vector<VIRTUAL_BUTTON_DESC> tempBtnDescs; |
| 136 | }; |
| 137 | |
| 138 | /** Provides easier access to VirtualInput. */ |
| 139 | BS_EXPORT VirtualInput& gVirtualInput(); |
| 140 | |
| 141 | /** @} */ |
| 142 | } |
| 143 | |