#pragma once #include "BsCorePrerequisites.h" #include "BsModule.h" #include "BsRect2I.h" #include "BsOSInputHandler.h" #include "BsRawInputHandler.h" #include "BsInputFwd.h" namespace BansheeEngine { /** * @brief Primary module used for dealing with input. Allows you to receieve * and query raw or OS input for mouse/keyboard/gamepad. * * All inputs are received through an input handler, which can be overriden to * provide custom input functionality. */ class BS_CORE_EXPORT Input : public Module { /** * @brief Possible button states */ enum class ButtonState { Off, /**< Button is not being pressed. */ On, /**< Button is being pressed. */ ToggledOn, /**< Button has been pressed this frame. */ ToggledOff, /**< Button has been released this frame. */ ToggledOnOff, /**< Button has been pressed and released this frame. */ }; /** * @brief Contains axis and device data per device */ struct DeviceData { DeviceData(); Vector axes; ButtonState keyStates[BC_Count]; }; /** * @brief Different types of possible input event callbacks. */ enum class EventType { ButtonUp, ButtonDown, PointerMoved, PointerUp, PointerDown, PointerDoubleClick, TextInput, Command }; /** * @brief Stores information about a queued input event that is to be triggered later. */ struct QueuedEvent { QueuedEvent(EventType type, UINT32 idx) :type(type), idx(idx) { } EventType type; UINT32 idx; }; public: Input(); ~Input(); /** * @brief Triggered whenever a button is first pressed. */ Event onButtonDown; /** * @brief Triggered whenever a button is first released. */ Event onButtonUp; /** * @brief Triggered whenever user inputs a text character. */ Event onCharInput; /** * @brief Triggers when some pointing device (mouse cursor, touch) moves. */ Event onPointerMoved; /** * @brief Triggers when some pointing device (mouse cursor, touch) button is pressed. */ Event onPointerPressed; /** * @brief Triggers when some pointing device (mouse cursor, touch) button is released. */ Event onPointerReleased; /** * @brief Triggers when some pointing device (mouse cursor, touch) button is double clicked. */ Event onPointerDoubleClick; // TODO Low priority: Remove this, I can emulate it using virtual input /** * @brief Triggers on special input commands. */ Event onInputCommand; /** * @brief Registers a new input handler. Replaces any previous input handler. * * @note Internal method. */ void _registerRawInputHandler(std::shared_ptr inputHandler); /** * @brief Called every frame. Detects button state changes and prepares callback events to trigger * via a call to "_triggerCallbacks". * * @note Internal method. */ void _update(); /** * @brief Triggers any queued input event callbacks. */ void _triggerCallbacks(); /** * @brief Returns value of the specified input axis. Normally in range [-1.0, 1.0] but can be outside * the range for devices with unbound axes (e.g. mouse). * * @param type Type of axis to query. Usually a type from InputAxis but can be a custom value. * @param deviceIdx Index of the device in case more than one is hooked up (0 - primary). */ float getAxisValue(UINT32 type, UINT32 deviceIdx = 0) const; /** * @brief Query if the provided button is currently being held (this frame or previous frames). * * @param keyCode Code of the button to query. * @param deviceIdx Device to query the button on (0 - primary). */ bool isButtonHeld(ButtonCode keyCode, UINT32 deviceIdx = 0) const; /** * @brief Query if the provided button is currently being released (only true for one frame). * * @param keyCode Code of the button to query. * @param deviceIdx Device to query the button on (0 - primary). */ bool isButtonUp(ButtonCode keyCode, UINT32 deviceIdx = 0) const; /** * @brief Query if the provided button is currently being pressed (only true for one frame). * * @param keyCode Code of the button to query. * @param deviceIdx Device to query the button on (0 - primary). */ bool isButtonDown(ButtonCode keyCode, UINT32 deviceIdx = 0) const; /** * @brief Returns position of the pointer (e.g. mouse cursor) relative to the screen. */ Vector2I getPointerPosition() const; /** * @brief Returns difference between last and current pointer position. */ Vector2I getPointerDelta() const { return mPointerDelta; } /** * @brief Query if the provided pointer button is currently * being held (this frame or previous frames). * * @param pointerButton Code of the button to query. */ bool isPointerButtonHeld(PointerEventButton pointerButton) const; /** * @brief Query if the provided pointer button is currently * being released (only true for one frame). * * @param pointerButton Code of the button to query. */ bool isPointerButtonUp(PointerEventButton pointerButton) const; /** * @brief Query if the provided pointer button is currently * being pressed (only true for one frame). * * @param pointerButton Code of the button to query. */ bool isPointerButtonDown(PointerEventButton pointerButton) const; /** * @brief Query has the left pointer button has been * double-clicked this frame. */ bool isPointerDoubleClicked() const; /** * @brief Enables or disables mouse smoothing. Smoothing makes the changes to * mouse axes more gradual. */ void setMouseSmoothing(bool enabled); private: /** * @brief Triggered by input handler when a button is pressed. */ void buttonDown(UINT32 deviceIdx, ButtonCode code, UINT64 timestamp); /** * @brief Triggered by input handler when a button is released. */ void buttonUp(UINT32 deviceIdx, ButtonCode code, UINT64 timestamp); /** * @brief Triggered by input handler when a single character is input. */ void charInput(UINT32 chr); /** * @brief Triggered by input handler when a mouse/joystick axis is moved. */ void axisMoved(UINT32 deviceIdx, const RawAxisState& state, UINT32 axis); /** * @brief Cursor movement as OS reports it. Used for screen cursor position. */ void cursorMoved(const PointerEvent& event); /** * @brief Cursor button presses as OS reports it. */ void cursorPressed(const PointerEvent& event); /** * @brief Cursor button releases as OS reports it. */ void cursorReleased(const PointerEvent& event); /** * @brief Cursor button releases as OS reports it. */ void cursorDoubleClick(const PointerEvent& event); /** * @brief Input commands as OS reports them. */ void inputCommandEntered(InputCommandType commandType); /** * @brief Called when window in focus changes, as reported by the OS. */ void inputWindowChanged(RenderWindow& win); private: std::shared_ptr mRawInputHandler; std::shared_ptr mOSInputHandler; Vector mDevices; Vector2I mPointerPosition; Vector2I mPointerDelta; ButtonState mPointerButtonStates[3]; bool mPointerDoubleClicked; bool mLastPositionSet; Vector mQueuedEvents; Vector mTextInputEvents; Vector mCommandEvents; Vector mPointerDoubleClickEvents; Vector mPointerReleasedEvents; Vector mPointerPressedEvents; Vector mPointerMovedEvents; Vector mButtonDownEvents; Vector mButtonUpEvents; /************************************************************************/ /* STATICS */ /************************************************************************/ static const int HISTORY_BUFFER_SIZE; // Size of buffer used for input smoothing static const float WEIGHT_MODIFIER; }; /** * @copydoc Input */ BS_CORE_EXPORT Input& gInput(); }